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

C语言二维动态数组调整大小问题:内存泄漏与访问错误

帮你搞定二维数组resize的两个坑:访问失败+内存泄漏

兄弟,我一看你这段代码就知道踩了几个C语言手动管理内存的经典坑,刚好我之前也遇到过类似的问题,给你拆解清楚:

1. 最致命的问题:参数传值导致外部指针没更新

你函数的参数是int **array,但C语言里参数是值传递——也就是说,函数里的array只是外部传入指针的一个副本。当你调用realloc(array, ...)的时候,修改的是这个副本的地址,而外部的原始指针根本没变化!

举个例子:外部原来的array指向0x1234,函数里的副本array被realloc改成0x5678,但外部的指针还是0x1234,这时候外部用array[i][j]访问的还是原来的旧内存,甚至可能已经被realloc回收了,自然会出问题。

解决方法:要么把参数改成指针的指针(int ***array),要么让函数返回新的指针。我更推荐后者,代码更清晰。

2. 明显的笔误:tomb[i]应该是array[i]

你的循环里写了realloc(tomb[i], ...),但函数里根本没有tomb这个参数啊!这明显是复制粘贴或者命名错误,应该改成array[i]。不然你操作的是完全无关的数组,原来的数组内存自然会泄漏,而且新数组的内容也会乱。

3. realloc的错误使用:直接赋值会导致内存泄漏

如果realloc失败,它会返回NULL。如果你直接写array = (int**)realloc(array, ...),一旦失败,原来的array指针就会被覆盖成NULL,原来的内存就再也找不到了,直接泄漏。

正确的做法是:先用临时变量接收realloc的结果,检查不为NULL再赋值给原指针。

4. 维度调整的逻辑混乱

看你的代码,newarraysize = WINDOWY/newsize,然后把每个一维数组的大小也改成newarraysize?这看起来逻辑有点奇怪——你是想把二维数组调整成newarraysize行,每行newarraysize个元素吗?如果是这样,那参数newsize的命名就很容易误导人,建议改成更清晰的名字,比如new_col_count或者直接计算目标行列数。


修正后的代码示例

我给你改了一版,解决了上面所有问题,你可以参考:

// 返回调整后的新指针,外部直接接收即可
int** resize(int **array, int new_rows, int old_rows, int new_cols, int old_cols) {
    // 先调整行指针数组的大小
    int** temp_array = (int**)realloc(array, new_rows * sizeof(int*));
    if (temp_array == NULL) {
        // realloc失败,返回原指针,避免内存丢失
        fprintf(stderr, "Failed to reallocate row pointers\n");
        return array;
    }
    array = temp_array;

    // 调整每行的元素大小
    if (new_rows > old_rows) {
        // 如果行数增加,旧行调整大小,新行需要malloc
        for (int i = 0; i < old_rows; i++) {
            int* temp_row = (int*)realloc(array[i], new_cols * sizeof(int));
            if (temp_row == NULL) {
                fprintf(stderr, "Failed to reallocate row %d\n", i);
                // 这里可以选择回滚已经分配的内存,避免泄漏
                return array;
            }
            array[i] = temp_row;
        }
        // 为新增的行分配内存
        for (int i = old_rows; i < new_rows; i++) {
            array[i] = (int*)malloc(new_cols * sizeof(int));
            if (array[i] == NULL) {
                fprintf(stderr, "Failed to allocate new row %d\n", i);
                // 回滚:释放新增的行
                for (int j = old_rows; j < i; j++) {
                    free(array[j]);
                }
                return array;
            }
            // 可选:初始化新行的内容,比如设为0
            memset(array[i], 0, new_cols * sizeof(int));
        }
    } else {
        // 如果行数减少,只调整保留的行的大小,多余的行要free避免泄漏
        for (int i = 0; i < new_rows; i++) {
            int* temp_row = (int*)realloc(array[i], new_cols * sizeof(int));
            if (temp_row == NULL) {
                fprintf(stderr, "Failed to reallocate row %d\n", i);
                return array;
            }
            array[i] = temp_row;
        }
        // 释放多余的行
        for (int i = new_rows; i < old_rows; i++) {
            free(array[i]);
        }
    }

    // 打印调试信息(可选)
    printf("\n");
    for(int i=0;i<new_rows;i++) {
        for(int j=0;j<new_cols;j++)
            printf("[%d][%d]: %p ",i,j,&array[i][j]);
        printf("\n");
    }

    return array;
}

使用方式

外部调用的时候,要这样接收返回值:

// 假设原来的数组是array,行数old_rows,列数old_cols
array = resize(array, new_rows, old_rows, new_cols, old_cols);
if (array == NULL) {
    // 处理分配失败的情况
}

额外注意事项

  • 如果你原来的二维数组是用malloc分配的,最后一定要记得逐层释放:先循环释放每个array[i],再释放array本身。
  • 尽量不要用魔法数字或者全局变量(比如WINDOWY),最好作为参数传入,代码更健壮。
  • 如果是C++环境,建议用std::vector代替手动管理二维数组,完全不用操心内存泄漏和resize的问题。

内容的提问来源于stack exchange,提问作者hokkyo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:50:59