C语言动态地图扩容第二次调用realloc报invalid next size错误求助
C语言动态二维数组realloc报错问题修复
错误原因
- 二级指针内存分配单位错误:
tab是char**类型,存储的是char*指针,分配内存时错误使用sizeof(char)作为单位,仅分配1字节/元素,远小于指针本身的大小(32位4字节/64位8字节),导致堆内存越界写入,破坏堆块元数据,第二次调用realloc时检测到堆结构损坏抛出realloc(): invalid next size错误。 - 上移边界判断逻辑错误:当前判断扩容的条件为
0 == myPath->y -1,仅当y=1时触发扩容,第一次上移完成后y=0,第二次上移会直接执行y-=1得到-1,后续数组访问下标越界。 - 坐标索引颠倒:
tab数组为tab[行号][列号]结构,行号对应y、列号对应x,代码中写入路径时写为tab[x][y],行列索引颠倒易触发越界。 - 内存释放逻辑缺失:
destroyPath仅释放tab本身,未先释放每个tab[i]指向的行内存,存在严重内存泄漏。 realloc使用不规范:直接将realloc返回值赋值给原指针,若申请失败返回NULL会丢失原指针,造成内存泄漏。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct{ char **tab; int x; // 列坐标 int y; // 行坐标 int ligne; // 总行数 int colonne; // 总列数 } Path; Path* InitPath(){ int i, j; Path *myPath = (Path*)malloc(sizeof(Path)); if(!myPath) return NULL; myPath->ligne = 3; myPath->colonne = 3; // 修复:分配char*大小的内存 myPath->tab = malloc(sizeof(char*) * myPath->ligne); if(!myPath->tab) { free(myPath); return NULL; } for(i=0; i< myPath->ligne; i++) { myPath->tab[i] = malloc(sizeof(char) * myPath->colonne); if(!myPath->tab[i]) { // 申请失败释放已分配内存 for(int k=0; k<i; k++) free(myPath->tab[k]); free(myPath->tab); free(myPath); return NULL; } } for(i=0; i<myPath->ligne; i++) { for(j=0; j<myPath->colonne; j++) { if( i ==1 && j ==1) myPath->tab[i][j] = 'S'; else myPath->tab[i][j] = '#'; } } myPath->x = 1; myPath->y = 1; return myPath; } void addWay(Path* myPath, const char* theWay){ int i; char** tmp_tab; if(strcmp("up", theWay) == 0){ // 修复:边界判断,当前已经是第一行,再往上走需要扩容 if(0 == myPath->y){ myPath->ligne +=1; // 修复:realloc使用临时指针接收,单位改为char* tmp_tab = realloc(myPath->tab, myPath->ligne * sizeof(char*)); if(!tmp_tab) return; myPath->tab = tmp_tab; myPath->tab[myPath->ligne-1] = malloc(sizeof(char) * myPath->colonne); if(!myPath->tab[myPath->ligne-1]) return; // 初始化新行 for(i = 0; i<myPath->colonne; i++){ if(i == 0 || i== myPath->colonne -1 ) myPath->tab[myPath->ligne-1][i] = '#'; else if (i == myPath->x) myPath->tab[myPath->ligne -1][i] = '*'; else myPath->tab[myPath->ligne -1][i] = ' '; } // 新行移到顶部 for(i = myPath->ligne -1; i > 0; i-- ){ char* tmp = myPath->tab[i]; myPath->tab[i] = myPath->tab[i-1]; myPath->tab[i-1] = tmp; } // 扩容后原有行号全部+1,当前坐标y也+1 myPath->y += 1; } // 上移 myPath->y -= 1; // 修复:行在前列在后,索引为tab[y][x] myPath->tab[myPath->y][myPath->x] = '*'; } } void showPath(Path* myPath){ int i, j; for(i=0; i< myPath->ligne; i++){ for(j=0; j< myPath->colonne; j++) printf("%c", myPath->tab[i][j]); printf("\n"); } } void destroyPath(Path* myPath){ if(!myPath) return; // 修复:先释放每行内存 for(int i=0; i<myPath->ligne; i++) { free(myPath->tab[i]); } free(myPath->tab); free(myPath); } int main(){ Path* new_path = InitPath(); if(!new_path) return 1; showPath(new_path); printf("**********************\n"); addWay(new_path, "up"); showPath(new_path); printf("**********************\n"); addWay(new_path, "up"); showPath(new_path); destroyPath(new_path); return 0; }
内容的提问来源于stack exchange,提问作者Dev Beginner
相关产品推荐
相关产品推荐

