更改读取输入大小时内存泄漏,headtail程序读取fail.txt无输出问题
问题根因
1. 核心崩溃原因:add_rows 函数野指针访问
扩容行存储区时,直接对新增的未初始化指针调用realloc,属于标准未定义行为,大概率直接导致程序崩溃无输出:
初始分配的field指针数组只有15个有效元素,调用add_rows扩容到25个元素后,下标15~24的指针都是未初始化的野指针,循环中对这些野指针执行realloc会直接触发非法内存访问。data.txt能正常运行是因为前14行长度都超过初始分配的15字节,频繁触发行扩容逻辑,还没等触发行数扩容程序就已经完成输入读取输出;而fail.txt前几行很短,读取到第14行时触发行扩容,直接触发野指针访问崩溃。
2. 内存校验逻辑错误
allocate函数中分配完columns数组后,错误判断matrix->field是否为空,若columns分配失败无法被捕获,后续访问columns数组也会触发野指针。
3. 行计数逻辑缺陷
last_changed仅在遇到换行符\n时才递增,若输入文件最后一行没有以换行符结尾,最后一行不会被计入总数,当要求输出的行数等于实际行数时会触发输出校验失败,无内容返回。
4. 类型使用不合理
行数为整数,不该用double存储num_of_output_lines,存在潜在精度风险。
修复方案
1. 修复add_rows函数,新增行直接分配内存
bool add_rows(TMatrix* matrix) { int old_rows = matrix->rows; matrix->rows += 10; char** rebuf = realloc(matrix->field, matrix->rows * sizeof(char*)); if (!rebuf) return false; matrix->field = rebuf; int* rebufl = realloc(matrix->columns, matrix->rows * sizeof(int)); if (!rebufl) return false; matrix->columns = rebufl; // 新增行直接malloc,不要realloc野指针 for (int i = old_rows; i < matrix->rows; i++) { matrix->field[i] = malloc(size * sizeof(char)); if (!matrix->field[i]) { // 释放已分配的新行避免泄漏 for (int j = old_rows; j < i; j++) free(matrix->field[j]); return false; } matrix->columns[i] = size; } return true; }
2. 修复allocate函数的校验逻辑
TMatrix* allocate() { TMatrix* matrix = malloc(sizeof(TMatrix)); if (!matrix) return NULL; matrix->field = malloc(size * sizeof(char*)); if (!matrix->field) { free(matrix); return NULL; } matrix->rows = size; matrix->columns = malloc(size * sizeof(int)); // 修正校验对象为columns if (!matrix->columns) { free(matrix->field); free(matrix); return NULL; } set_size(matrix); for (int i = 0; i < matrix->rows; i++) { matrix->field[i] = malloc(size * sizeof(char)); if (!matrix->field[i]) { for (int j = 0; j < i; j++) free(matrix->field[j]); free(matrix->columns); free(matrix->field); free(matrix); return NULL; } } return matrix; }
3. 修复行计数逻辑,处理无结尾换行的文件
在load函数的while循环结束后增加如下代码:
// 处理最后一行无换行的场景 if (actual_column > 0) { matrix->field[actual_row][actual_column] = '\0'; last_changed += 1; }
4. 修正行数类型
将output函数的num_of_output_lines参数改为int类型,main函数中对应修改为:
int num_of_output_lines = atoi(argv[argc - 1]);
内容的提问来源于stack exchange,提问作者Ghost123
相关产品推荐
相关产品推荐

