You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 19:57:32