C语言读取文件转二维数组时出现内存泄漏,求排查修复
内存泄漏排查与修复方案
常见泄漏点分析
结合你的场景和Valgrind报告,大概率是以下问题导致泄漏:
- 未释放
getline分配的每行临时内存 - 二维数组(
char **)本身未被回收 - 内存分配失败时未清理已分配的资源
- 文件操作异常后未处理残留内存
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> // 自行实现的realloc void *my_realloc(void *ptr, size_t old_size, size_t new_size) { if (new_size == 0) { free(ptr); return NULL; } void *new_ptr = malloc(new_size); if (!new_ptr) return NULL; if (ptr && old_size > 0) { size_t copy_len = old_size < new_size ? old_size : new_size; memcpy(new_ptr, ptr, copy_len); free(ptr); } return new_ptr; } char **load_file(const char *filename, size_t *out_line_count) { FILE *fp = fopen(filename, "r"); if (!fp) { perror("fopen failed"); return NULL; } char **lines = NULL; size_t line_count = 0; char *line = NULL; size_t len = 0; ssize_t read_len; while ((read_len = getline(&line, &len, fp)) != -1) { // 可选:去除换行符 if (read_len > 0 && line[read_len - 1] == '\n') { line[read_len - 1] = '\0'; } // 扩展二维数组空间 char **temp_lines = my_realloc(lines, line_count * sizeof(char *), (line_count + 1) * sizeof(char *)); if (!temp_lines) { perror("realloc failed"); // 清理已分配的所有内存 for (size_t i = 0; i < line_count; i++) free(lines[i]); free(lines); free(line); fclose(fp); return NULL; } lines = temp_lines; // 独立分配每行内存,避免复用getline的临时指针 lines[line_count] = malloc(strlen(line) + 1); if (!lines[line_count]) { perror("malloc line failed"); for (size_t i = 0; i < line_count; i++) free(lines[i]); free(lines); free(line); fclose(fp); return NULL; } strcpy(lines[line_count], line); line_count++; } // 释放getline分配的最后一块临时内存 free(line); fclose(fp); // 添加终止NULL指针,方便后续遍历 char **final_lines = my_realloc(lines, line_count * sizeof(char *), (line_count + 1) * sizeof(char *)); if (final_lines) { lines = final_lines; lines[line_count] = NULL; } if (out_line_count) *out_line_count = line_count; return lines; } // 专用内存释放函数 void free_lines(char **lines) { if (!lines) return; for (size_t i = 0; lines[i]; i++) free(lines[i]); free(lines); } int main() { size_t line_count; char **lines = load_file("test.txt", &line_count); if (!lines) return 1; // 测试输出(可选) for (size_t i = 0; i < line_count; i++) { printf("Line %zu: %s\n", i, lines[i]); } // 释放所有内存 free_lines(lines); return 0; }
关键修复点说明
- 独立分配每行内存:不再直接存储
getline返回的指针,而是复制到新分配的内存中,避免getline复用指针导致的内存管理混乱。 - 错误时的全量清理:内存分配失败时,遍历释放已分配的所有行内存和二维数组,彻底避免泄漏。
- 回收
getline临时内存:循环结束后必须调用free(line),即使最后一次读取失败,getline也可能已分配内存。 - 专用释放函数:
free_lines负责遍历释放每行内存,最后回收二维数组,确保所有分配的资源都被回收。 - 添加终止NULL指针:方便后续遍历判断结束,同时保证二维数组的结构完整性。
Valgrind验证效果
修复后运行Valgrind检测,应显示无明确泄漏:
==xxxx== LEAK SUMMARY: ==xxxx== definitely lost: 0 bytes in 0 blocks ==xxxx== indirectly lost: 0 bytes in 0 blocks ==xxxx== possibly lost: 0 bytes in 0 blocks ==xxxx== still reachable: 0 bytes in 0 blocks ==xxxx== suppressed: 0 bytes in 0 blocks
内容的提问来源于stack exchange,提问作者Nayrosk
相关产品推荐
相关产品推荐

