C语言矩阵生成打印代码出现段错误,询问原因及内存释放方法
问题根源分析
- 首先是参数传递错误:C语言默认是值传递,你给
makeMatrix传入的test指针是实参拷贝,函数内给M赋值的malloc地址无法回传给外层的test变量,导致test始终是未初始化的野指针,printMatrix访问野指针直接触发段错误。 - 其次是内存释放时机错误:你在
makeMatrix函数内刚完成矩阵初始化就调用free(M)释放了刚申请的矩阵内存,就算地址能传到外层,后续访问的也是已经被回收的非法内存,同样会触发段错误。 - 最后是内存分配冗余:
M->m = malloc(100*sizeof(double)*M->rows*M->cols);这里多乘了不必要的系数100,会造成内存浪费,实际只需要按矩阵元素个数申请即可。
修复方案
方法1:修改makeMatrix为返回指针的形式
// 改为返回构造好的矩阵指针 struct Matrix* makeMatrix(int row, int col, int num){ struct Matrix *M = malloc(sizeof(struct Matrix)); // 增加malloc失败判空处理,避免野指针 if(!M) return NULL; M->rows = row; M->cols = col; // 去掉冗余的100倍系数 M->m = malloc(sizeof(double) * M->rows * M->cols); if(!M->m) { free(M); return NULL; } for(int i=0; i<M->rows;i++){ for(int j=0; j<M->cols;j++){ setVal(M,i,j,num); } } // 不要在这里释放,返回给外层使用 return M; } // 新增专门的内存释放函数,用完矩阵后调用 void freeMatrix(struct Matrix *M) { if(M) { // 先释放存储元素的内存块 free(M->m); // 再释放矩阵结构体本身 free(M); } } int main(int argc, char const *argv[]) { struct Matrix *test = makeMatrix(10,10,10); if(test) { printMatrix(test); // 确认矩阵不再使用后再释放 freeMatrix(test); } return 0; }
方法2:使用二级指针作为参数
如果不想修改函数返回值,也可以用二级指针接收内存地址:
void makeMatrix(struct Matrix **M, int row, int col, int num){ *M = malloc(sizeof(struct Matrix)); if(!(*M)) return; (*M)->rows = row; (*M)->cols = col; (*M)->m = malloc(sizeof(double) * row * col); if(!(*M)->m) { free(*M); *M = NULL; return; } for(int i=0; i<row;i++){ for(int j=0; j<col;j++){ setVal(*M,i,j,num); } } } int main(int argc, char const *argv[]) { struct Matrix *test; makeMatrix(&test,10,10,10); if(test) { printMatrix(test); freeMatrix(test); } return 0; }
内存释放注意事项
- 必须遵循「先申请后释放、后申请先释放」的顺序,先释放矩阵内部存储元素的
m成员,再释放矩阵结构体本身,避免产生内存泄漏。 - 所有
malloc申请的内存都必须对应一次free调用,且只能在确认内存完全不再使用后再执行释放操作。
内容的提问来源于stack exchange,提问作者Shehab A
相关产品推荐
相关产品推荐

