C语言链表动态内存释放问题及内存泄漏排查
C语言链表内存泄漏问题解决
问题背景
在C语言实现链表时,insertStart函数中通过malloc分配的newEntry出现内存泄漏。已尝试实现deleteAll方法,但Valgrind检测仍显示该位置存在20字节的明确泄漏。
现有代码
main函数
void main() { LinkedList* undo = createLinkedList(); Position* place = (Position*)malloc(sizeof(Position)); place->row = 1; place->col = 2; insertStart(undo, (void*)place); }
insertStart函数
void insertStart(LinkedList* list, void* entry) { void* newEntry = malloc(sizeof(Position)); ListNode* newNd = (ListNode*)malloc(sizeof(ListNode)); memcpy(newEntry, entry, sizeof(Position)); newNd->data = newEntry; newNd->next = list->head; list->head = newNd; list->size++; }
Valgrind检测结果
初始检测结果
==1385== ==1385== HEAP SUMMARY: ==1385== in use at exit: 900 bytes in 19 blocks ==1385== total heap usage: 78 allocs, 59 frees, 14,808 bytes allocated ==1385== ==1385== 20 bytes in 1 blocks are definitely lost in loss record 1 of 7 ==1385== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==1385== by 0x109668: controls (game.c:78) ==1385== by 0x109596: game (game.c:44) ==1385== by 0x109455: main (main.c:49) ==1385== ==1385== 48 bytes in 2 blocks are indirectly lost in loss record 2 of 7 ==1385== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==1385== by 0x10AA5B: insertStart (linkedList.c:24) ==1385== by 0x109829: controls (game.c:114) ==1385== by 0x109596: game (game.c:44) ==1385== by 0x109455: main (main.c:49) ==1385== ==1385== 48 bytes in 2 blocks are indirectly lost in loss record 3 of 7 ==1385== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==1385== by 0x10AA5B: insertStart (linkedList.c:24) ==1385== by 0x1099F2: controls (game.c:144) ==1385== by 0x109596: game (game.c:44) ==1385== by 0x109455: main (main.c:49) ==1385== ==1385== 120 bytes in 5 blocks are indirectly lost in loss record 4 of 7 ==1385== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==1385== by 0x10AA5B: insertStart (linkedList.c:24) ==1385== by 0x109910: controls (game.c:129) ==1385== by 0x109596: game (game.c:44) ==1385== by 0x109455: main (main.c:49) ==1385== ==1385== 168 bytes in 7 blocks are indirectly lost in loss record 5 of 7 ==1385== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==1385== by 0x10AA5B: insertStart (linkedList.c:24) ==1385== by 0x109AD9: controls (game.c:159) ==1385== by 0x109596: game (game.c:44) ==1385== by 0x109455: main (main.c:49) ==1385== ==1385== 408 (24 direct, 384 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 7 ==1385== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==1385== by 0x10AA5B: insertStart (linkedList.c:24) ==1385== by 0x109AD9: controls (game.c:159) ==1385== by 0x109596: game (game.c:44) ==1385== by 0x109455: main (main.c:49) ==1385== ==1385== 472 bytes in 1 blocks are still reachable in loss record 7 of 7 ==1385== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==1385== by 0x48DF64D: __fopen_internal (iofopen.c:65) ==1385== by 0x48DF64D: fopen@@GLIBC_2.2.5 (iofopen.c:86) ==1385== by 0x109347: main (main.c:26) ==1385== ==1385== LEAK SUMMARY: ==1385== definitely lost: 44 bytes in 2 blocks ==1385== indirectly lost: 384 bytes in 16 blocks ==1385== possibly lost: 0 bytes in 0 blocks ==1385== still reachable: 472 bytes in 1 blocks ==1385== suppressed: 0 bytes in 0 blocks ==1385== ==1385== For lists of detected and suppressed errors, rerun with: -s ==1385== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
实现deleteAll后的检测结果
==3055== ==3055== HEAP SUMMARY: ==3055== in use at exit: 20 bytes in 1 blocks ==3055== total heap usage: 72 allocs, 71 frees, 14,676 bytes allocated ==3055== ==3055== 20 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==3055== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3055== by 0x10AA80: insertStart (linkedList.c:22) ==3055== by 0x109A1E: controls (game.c:144) ==3055== by 0x1095C2: game (game.c:44) ==3055== by 0x109475: main (main.c:49) ==3055== ==3055== LEAK SUMMARY: ==3055== definitely lost: 20 bytes in 1 blocks ==3055== indirectly lost: 0 bytes in 0 blocks ==3055== possibly lost: 0 bytes in 0 blocks ==3055== still reachable: 0 bytes in 0 blocks ==3055== suppressed: 0 bytes in 0 blocks ==3055== ==3055== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
问题分析与解决方案
核心问题
你实现的deleteAll大概率只释放了链表节点(ListNode)本身,没有释放节点中存储的data指针指向的内存(也就是insertStart里malloc的newEntry)。另外,main函数中手动分配的place也没有释放,不过当前Valgrind提示的泄漏来自newEntry。
正确的deleteAll实现
void deleteAll(LinkedList* list) { ListNode* current = list->head; while (current != NULL) { ListNode* next = current->next; // 先释放节点存储的数据内存 free(current->data); // 再释放节点本身 free(current); current = next; } // 重置链表状态 list->head = NULL; list->size = 0; }
完善main函数的内存释放
在使用完链表后,调用deleteAll释放所有节点和数据,然后释放链表本身(如果createLinkedList是通过malloc分配的),同时释放main中分配的place:
void main() { LinkedList* undo = createLinkedList(); Position* place = (Position*)malloc(sizeof(Position)); place->row = 1; place->col = 2; insertStart(undo, (void*)place); // insert后place已不再需要,直接释放 free(place); // 使用链表的逻辑... // 清理链表 deleteAll(undo); // 释放链表结构体本身(如果createLinkedList是malloc的) free(undo); }
验证
重新编译后用Valgrind检测,应该能消除所有明确的内存泄漏。
内容的提问来源于stack exchange,提问作者Cindy_ l
相关产品推荐
相关产品推荐

