无法定位C程序内存泄漏原因?求分析Valgrind检测结果
内存泄漏排查:查找最长句子的C程序问题
程序代码
/* lngst_sentence_file_competition.c */ #include <stdio.h> #include <stdlib.h> enum consts { str_len = 5 }; typedef struct tag_item { int sentence_length; char *sentence; struct tag_item *next; } item; void free_str_if_it_is_not_lngst( char **str, char **lngst_file_str, int *curr_sentence_len, int *file_lngst_sentence_len ) { if (*curr_sentence_len <= *file_lngst_sentence_len) free(*str); else { if (*lngst_file_str) { free(*lngst_file_str); *lngst_file_str = NULL; } *lngst_file_str = *str; *file_lngst_sentence_len = *curr_sentence_len; } *curr_sentence_len = 0; *str = NULL; } void find_lngst_sentence_in_next_file( FILE *file, char **lngst_file_str, int *lngst_sentence_len ) { char *str = malloc(str_len*sizeof(char)); int str_mem_size = str_len; int c; int curr_sentence_len = 0; int file_lngst_sentence_len = 0; while ((c=fgetc(file)) != EOF) { switch (c) { case '.': str[curr_sentence_len] = '.'; str[curr_sentence_len + 1] = '\0'; free_str_if_it_is_not_lngst( &str, lngst_file_str, &curr_sentence_len, &file_lngst_sentence_len ); str = malloc(str_len*sizeof(char)); str_mem_size = str_len; /* falls through */ case '\n': case '\t': continue; } curr_sentence_len++; if (curr_sentence_len+1 == str_mem_size) { str = realloc(str, str_mem_size + str_len); str_mem_size += str_len; } str[curr_sentence_len - 1] = c; } free_str_if_it_is_not_lngst( &str, lngst_file_str, &curr_sentence_len, &file_lngst_sentence_len ); if (*lngst_sentence_len < file_lngst_sentence_len) *lngst_sentence_len = file_lngst_sentence_len; } int main(int argc, char **argv) { FILE *file; item *first = NULL; int lngst_sentence_len = 0; int i; for (i=1; i < argc; i++) { char *str = NULL; file = fopen(argv[i], "r"); if (!file) { perror(argv[i]); exit(1); } find_lngst_sentence_in_next_file(file, &str, &lngst_sentence_len); printf("%s\nString length is %d.\n", str, lngst_sentence_len); /* add_new_element_to_linked_list(&first, str); */ } /* print_sentences(first); */ return 0; }
测试文件内容
a. ab. abc.
Valgrind检测命令
valgrind --tool=memcheck --leak-check=full -s ./lngst_sentence_file_competition test.txt
Valgrind输出结果
==359271== abc. String length is 3. ==359271== ==359271== HEAP SUMMARY: ==359271== in use at exit: 477 bytes in 2 blocks ==359271== total heap usage: 7 allocs, 5 frees, 5,612 bytes allocated ==359271== ==359271== 5 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==359271== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==359271== by 0x109389: find_lngst_sentence_in_next_file (lngst_sentence_file_competition.c:53) ==359271== by 0x1094F4: main (lngst_sentence_file_competition.c:87) ==359271== ==359271== LEAK SUMMARY: ==359271== definitely lost: 5 bytes in 1 blocks ==359271== indirectly lost: 0 bytes in 0 blocks ==359271== possibly lost: 0 bytes in 0 blocks ==359271== still reachable: 472 bytes in 1 blocks ==359271== suppressed: 0 bytes in 0 blocks ==359271== Reachable blocks (those to which a pointer was found) are not shown. ==359271== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==359271== ==359271== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
泄漏原因与修复方案
泄漏的核心原因是main函数中没有释放str指向的内存:
- 在
find_lngst_sentence_in_next_file函数中,最长句子的内存会被赋值给传入的str指针,这个内存块在函数内不会被释放(因为它是当前文件的最长句)。 - 回到main函数后,你只在printf中使用了这个
str,但没有调用free(str)释放它,程序退出时这块内存就成了泄漏点。
另外,当前代码fopen文件后没有调用fclose(file),这也会导致文件资源泄漏(Valgrind标注的still reachable字节与此有关)。
修复代码只需在main函数的printf之后添加两行:
free(str); fclose(file);
修改后的main函数对应片段:
find_lngst_sentence_in_next_file(file, &str, &lngst_sentence_len); printf("%s\nString length is %d.\n", str, lngst_sentence_len); free(str); fclose(file);
内容的提问来源于stack exchange,提问作者Fyodor
相关产品推荐
相关产品推荐

