C语言结构体中二维数组内存释放 Valgrind提示未释放问题排查
问题原因分析
你的代码存在两个核心问题,共同导致了内存完全没有被释放:
- 释放逻辑和申请逻辑的循环次数不匹配
你在buildfield函数中为game->field申请了20个int*类型的指针,每个指针都单独申请了内存,但是在freefield函数中仅循环了传入的length值(也就是10)次,仅尝试释放前10个指针指向的内存,剩下10个指针对应的内存本身就没有被纳入释放逻辑。 - 存在数组越界访问,程序提前崩溃,释放代码完全没有执行
这是Valgrind显示0 frees的直接原因,你的代码有两处明确的越界访问:
buildfield的初始化循环中for (int col = 0; col < 81; col++),但game->field总共只申请了20个元素,col≥20时就已经访问了非法内存,触发未定义行为,绝大多数情况下会直接导致程序段错误终止,后续的freefield、free(game)逻辑完全没有运行的机会。printfield中的数组下标写反:你内层循环j的范围是0~19,但game->field[i]仅申请了10个int元素,game->field[i][j]在j≥10时就已经越界,也会触发程序崩溃。
修复方案
你可以按照以下逻辑修改代码:
- 建议把行列常量用宏定义统一管理,避免魔数不匹配的问题
- 修正越界访问的下标
- 修正释放逻辑的循环次数
修改后的核心代码示例:
// 顶部加宏定义 #define FIELD_COL 20 #define FIELD_LINE 10 void buildfield(Game* game, int length) { game->field = (int**)malloc((sizeof (int*)) * FIELD_COL); int i; for (i = 0; i < FIELD_COL; i++) { game->field[i] = (int*) malloc((sizeof (int)) * length); } // 修正col上限 for (int line = 0; line < length; line++) { for (int col = 0; col < FIELD_COL; col++) { game->field[col][line] = 0; } } } void printfield(Game* game, int length) { for (int i = 0; i < length; i++) { printf("\n"); for (int j = 0; j < FIELD_COL; j++) { // 修正下标顺序 printf("%d",game->field[j][i]); } } } void freefield(Game* game, int length) { // 修正循环次数为申请的列数 for (int i = 0; i < FIELD_COL; ++i) { free(game->field[i]); } free(game->field); }
修改后重新编译运行,Valgrind就可以检测到所有内存都被正常释放了。
内容的提问来源于stack exchange,提问作者David To
相关产品推荐
相关产品推荐

