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
相关产品推荐
相关产品推荐

