You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 14:06:04