C语言动态分配二维矩阵出现段错误,求原因分析
C语言二维矩阵动态分配的段错误问题分析
我是C语言初学者,正在学习二维矩阵的动态分配。在main函数中用10和11作为测试尺寸时,insert_values函数执行时能正常输出,但调用print_values函数会触发段错误,请求帮忙分析问题原因。
代码示例
#include <stdio.h> #include <stdlib.h> void insert_values(int **arr, int dim, int size); void resize(int ***arr, int dim) { if (*arr == NULL) { *arr = (int **)malloc(dim * sizeof(int *)); if (!*arr) return; } else { *arr = (int **)realloc(*arr, dim * sizeof(int *)); if (*arr == NULL) return; } for (int i = 0; i < dim; i++) { if ((*arr)[i] == NULL) { (*arr)[i] = (int *)malloc(dim * sizeof(int)); if (!(*arr)[i]) return; break; } else { //如果该位置已存在则重新分配 (*arr)[i] = (int *)realloc(**arr, dim * sizeof(int)); if ((*arr)[i] == NULL) return; } } } void insert_values(int **arr, int dim, int size) { if (size > dim) { resize(&(arr), size); } int x; int y; for(x = 0; x < size; x++) { for (y = 0; y < size; y++) { arr[x][y] = x + y; printf("%d |", arr[x][y]); } printf("\n"); } } void print_values(int **arr, int size) { for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { printf("%d |", *(arr+i)[j]); } printf("\n"); } } int main(int argc, char *argv[]) { int **x = (int**)malloc(10 * sizeof(*x)); if (!x) { return 0; } for (int i = 0; i < 10; i++) { x[i] = (int*)malloc(10 * sizeof(int)); } insert_values(x, 10, 11); print_values(x, 11); for (int i = 0; i < 10; i++) { free(x[i]); } free(x); }
运行输出
0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 | 1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 | 2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 | 3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 | 4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 | 5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 | 6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |16 | 7 |8 |9 |10 |11 |12 |13 |14 |15 |16 |17 | 8 |9 |10 |11 |12 |13 |14 |15 |16 |17 |18 | 9 |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 | 10 |11 |12 |13 |14 |15 |16 |17 |18 |19 |20 | -533986992 |-533955728 |
问题原因分析
1. 函数参数传递错误,主函数指针未更新
insert_values中调用resize(&arr, size)时,arr是函数的形参,修改形参的地址不会同步到main函数的x指针。也就是说,resize内部把arr扩容到11个指针,但main里的x仍是原来仅10个指针的数组。后续print_values用x访问第11个元素(x[10])属于数组越界,触发非法内存访问。
2. resize函数循环逻辑完全错误
- 循环遇到
(*arr)[i] == NULL时,分配空间后直接break,仅处理第一个符合条件的元素,其余行(包括新增的行)都未正确分配/扩容。 realloc参数错误:realloc(**arr, dim * sizeof(int))中,**arr是arr[0][0]的值,而非要扩容的行指针(*arr)[i],会错误修改行指针指向,破坏内存结构。
3. print_values运算符优先级错误
*(arr+i)[j]的写法存在优先级问题:[]优先级高于*,表达式等价于*(arr+i+j),即访问arr[i+j]的首元素,而非第i行第j列的元素。当i=10时,arr+i+j指向arr[10],超出main中x的数组范围,触发段错误。
4. 内存管理漏洞
- 扩容后新增的行指针未被释放,造成内存泄漏。
realloc失败时会丢失原有行指针,同样导致内存泄漏。
修正建议
修改
insert_values参数为指针的指针,确保resize能修改主函数的原始指针:void insert_values(int ***arr, int dim, int size) { if (size > dim) { resize(arr, size); } // 后续访问改为 (*arr)[x][y] } // main中调用:insert_values(&x, 10, 11);修复
resize循环逻辑,遍历所有行正确处理:void resize(int ***arr, int new_dim) { int old_dim = (*arr != NULL) ? 10 : 0; // 示例中原维度为10,更严谨的做法是传入原维度 // 先扩容指针数组 int **tmp = realloc(*arr, new_dim * sizeof(int *)); if (!tmp) return; *arr = tmp; // 处理每一行 for (int i = 0; i < new_dim; i++) { if (i >= old_dim) { (*arr)[i] = malloc(new_dim * sizeof(int)); } else { int *row_tmp = realloc((*arr)[i], new_dim * sizeof(int)); if (!row_tmp) return; (*arr)[i] = row_tmp; } } }修正
print_values的访问方式:void print_values(int **arr, int size) { for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { printf("%d |", arr[i][j]); } printf("\n"); } }根据最终矩阵尺寸释放所有行:
// main中print后释放11行 for (int i = 0; i < 11; i++) { free(x[i]); } free(x);
内容的提问来源于stack exchange,提问作者Karim Mahmoud
相关产品推荐
相关产品推荐

