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

C语言中realloc()调整矩阵大小时无法正确复制数据的问题求助

问题:C语言中double**矩阵resize后数据未正确复制

我尝试在C语言中调整double**类型矩阵的大小,理论上realloc()会把旧矩阵的数据复制到新调整后的矩阵里,但实际矩阵中的值要么没正确复制,要么呈现随机值。不过矩阵的行数和列数调整是正常的,打印的行列数正确。

原代码

double **matrix_resize(double **m, int rows, int cols) 
{
    int i;
    double **safe;
    safe = realloc(m, rows * sizeof(double*));
    if (safe == NULL) return NULL;
    m = safe;
    for (i = 0; i < rows; ++i) {
        double *safe2 = realloc(m[i], cols * sizeof(double));
        if (safe2 == NULL) {
            free(safe2);
            free(safe);
            return NULL;
        }
        m[i] = safe2;
        free(safe2);
    }
    free(safe);
    return m;
}

预期与实际结果

预期

函数返回具有新行列数的矩阵,旧数据完整复制到新矩阵中。

实际输出

old matrix:

-----0---1---2---
0: | 1 | 1 | 1 |
---------------
1: | 1 | 1 | 1 |
---------------
2: | 1 | 1 | 1 |
---------------

resized matrix:

-----0---1---2---3---4---
0: | 0 | 0 | 1 | 0 | 1 |
-------------------------
1: | 0 | 0 | 0 | 0 | 0 |
-------------------------
2: | 1 | 1 | 1 | 0 | 0 |
-------------------------
3: | 0 | 0 | 1 | 0 | 0 |
-------------------------
4: | 0 | 0 | 1 | 0 | 0 |
-------------------------

问题分析与修正

原代码存在两处致命错误:

  • 错误释放safe2:在m[i] = safe2;之后立即free(safe2),导致m[i]指向的内存被释放,后续访问时会读取到随机值或已回收的内存数据。realloc返回的指针就是新的内存地址,不需要手动释放,应该让m[i]持有这个地址。
  • 错误释放safe:最后free(safe);会把整个矩阵的行指针数组释放,返回的m此时指向已释放的内存,完全无效。

此外,错误处理部分也有问题:当某一行realloc失败时,应该先释放已经成功调整的行,再释放行指针数组,避免内存泄漏。

修正后的代码

double **matrix_resize(double **m, int rows, int cols) 
{
    int i;
    double **safe = realloc(m, rows * sizeof(double*));
    if (safe == NULL) {
        return NULL;
    }
    m = safe;

    // 先处理所有行的realloc,失败时回滚已分配的内存
    for (i = 0; i < rows; ++i) {
        double *safe2 = realloc(m[i], cols * sizeof(double));
        if (safe2 == NULL) {
            // 释放已经成功调整的行
            for (int j = 0; j < i; ++j) {
                free(m[j]);
            }
            free(safe);
            return NULL;
        }
        m[i] = safe2;
    }

    return m;
}

补充说明

  • realloc的行为:如果新的内存大小比原来大,会把旧数据复制到新内存的前半部分,新增的部分会被初始化为不确定值;如果新大小更小,会截断旧数据。
  • 当扩展行数时,新增加的行指针m[i](原矩阵没有的行)是realloc新增的,初始值为不确定值,需要手动初始化为NULL或者分配内存。如果需要初始化新增行,可以在循环中对原矩阵不存在的行单独处理:
// 假设函数新增参数old_rows表示原矩阵行数
double *safe2;
if (i < old_rows) {
    safe2 = realloc(m[i], cols * sizeof(double));
} else {
    safe2 = malloc(cols * sizeof(double));
    if (safe2 != NULL) {
        memset(safe2, 0, cols * sizeof(double)); // 初始化为0
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:35:17