繁体   English   中英

如何修复 C 程序中的 memory 泄漏?

[英]How to fix memory leak in C program?

下面的 C 程序应该分配一个列表,然后释放它并同时打印它的内容:

#include <stdlib.h>
#include <stdio.h>
typedef struct {
struct chain *next;       
int contents;  } chain; 

int main()  {     
    int index;     
    chain *list;     
    chain *p;    
    chain *pointer;     
    list = malloc(sizeof(chain));     
    p = list;     

    for(index=0;index<10;index++) {       
        (*p).contents = index;       
        (*p).next = malloc(sizeof(chain));       
        p = (*p).next; 
       } ;     
    p = pointer = list;     
    index = 0;     

    while (index < 9) { 
        printf("cell # %d: %d\n",index,(*p).contents);       
        p = (*p).next;       
        free(pointer);       
        pointer = p;       
        index++; 
      } ;     
    printf("First cell: %d\n",(*list).contents); 
    return 0;  
  } 

当我使用完整的泄漏检查运行 Valgrind 时,我得到以下日志,指示 2 个错误/内存泄漏:

--13792-- REDIR: 0x401f2f0 (ld-linux-x86-64.so.2:strlen) redirected to 0x580608c1 (???)
--13792-- REDIR: 0x401f0d0 (ld-linux-x86-64.so.2:index) redirected to 0x580608db (???)
--13792-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so
--13792--   Considering /usr/lib/valgrind/vgpreload_core-amd64-linux.so ..
--13792--   .. CRC mismatch (computed 50df1b30 wanted 4800a4cf)
--13792--    object doesn't have a symbol table
--13792-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so
--13792--   Considering /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so ..
--13792--   .. CRC mismatch (computed f893b962 wanted 95ee359e)
--13792--    object doesn't have a symbol table
==13792== WARNING: new redirection conflicts with existing -- ignoring it
--13792--     old: 0x0401f2f0 (strlen              ) R-> (0000.0) 0x580608c1 ???
--13792--     new: 0x0401f2f0 (strlen              ) R-> (2007.0) 0x04c32db0 strlen
--13792-- REDIR: 0x401d360 (ld-linux-x86-64.so.2:strcmp) redirected to 0x4c33ee0 (strcmp)
--13792-- REDIR: 0x401f830 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4c374f0 (mempcpy)
--13792-- Reading syms from /lib/x86_64-linux-gnu/libc-2.27.so
--13792--   Considering /lib/x86_64-linux-gnu/libc-2.27.so ..
--13792--   .. CRC mismatch (computed b1c74187 wanted 042cc048)
--13792--   Considering /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.27.so ..
--13792--   .. CRC is valid
--13792-- REDIR: 0x4edac70 (libc.so.6:memmove) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9d40 (libc.so.6:strncpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edaf50 (libc.so.6:strcasecmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9790 (libc.so.6:strcat) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9d70 (libc.so.6:rindex) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edc7c0 (libc.so.6:rawmemchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edade0 (libc.so.6:mempcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edac10 (libc.so.6:bcmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9d00 (libc.so.6:strncmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9800 (libc.so.6:strcmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edad40 (libc.so.6:memset) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ef80f0 (libc.so.6:wcschr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9ca0 (libc.so.6:strnlen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9870 (libc.so.6:strcspn) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edafa0 (libc.so.6:strncasecmp) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9840 (libc.so.6:strcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edb0e0 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9da0 (libc.so.6:strpbrk) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed97c0 (libc.so.6:index) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ed9c70 (libc.so.6:strlen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ee46c0 (libc.so.6:memrchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edaff0 (libc.so.6:strcasecmp_l) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edabe0 (libc.so.6:memchr) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4ef8eb0 (libc.so.6:wcslen) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4eda050 (libc.so.6:strspn) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edaf20 (libc.so.6:stpncpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edaef0 (libc.so.6:stpcpy) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edc7f0 (libc.so.6:strchrnul) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4edb040 (libc.so.6:strncasecmp_l) redirected to 0x4a2a6e0 (_vgnU_ifunc_wrapper)
--13792-- REDIR: 0x4fca3c0 (libc.so.6:__strrchr_avx2) redirected to 0x4c32730 (rindex)
--13792-- REDIR: 0x4ed3070 (libc.so.6:malloc) redirected to 0x4c2faa0 (malloc)
--13792-- REDIR: 0x4fca1d0 (libc.so.6:__strchrnul_avx2) redirected to 0x4c37020 (strchrnul)
--13792-- REDIR: 0x4fcaab0 (libc.so.6:__mempcpy_avx_unaligned_erms) redirected to 0x4c37130 (mempcpy)
cell # 0: 0
--13792-- REDIR: 0x4ed3950 (libc.so.6:free) redirected to 0x4c30cd0 (free)
cell # 1: 1
cell # 2: 2
cell # 3: 3
cell # 4: 4
cell # 5: 5
cell # 6: 6
cell # 7: 7
cell # 8: 8
cell # 9: 9
==13792== Invalid read of size 4
==13792==    at 0x108797: main (dynmem.c:31)
==13792==  Address 0x522d048 is 8 bytes inside a block of size 16 free'd
==13792==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13792==    by 0x108780: main (dynmem.c:27)
==13792==  Block was alloc'd at
==13792==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13792==    by 0x1086EB: main (dynmem.c:15)
==13792== 
First cell: 0
==13792== 
==13792== HEAP SUMMARY:
==13792==     in use at exit: 16 bytes in 1 blocks
==13792==   total heap usage: 12 allocs, 11 frees, 1,200 bytes allocated
==13792== 
==13792== Searching for pointers to 1 not-freed blocks
==13792== Checked 70,200 bytes
==13792== 
==13792== 16 bytes in 1 blocks are definitely lost in loss record 1 of 1
==13792==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13792==    by 0x108714: main (dynmem.c:19)
==13792== 
==13792== LEAK SUMMARY:
==13792==    definitely lost: 16 bytes in 1 blocks
==13792==    indirectly lost: 0 bytes in 0 blocks
==13792==      possibly lost: 0 bytes in 0 blocks
==13792==    still reachable: 0 bytes in 0 blocks
==13792==         suppressed: 0 bytes in 0 blocks
==13792== 
==13792== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==13792== 
==13792== 1 errors in context 1 of 2:
==13792== Invalid read of size 4
==13792==    at 0x108797: main (dynmem.c:31)
==13792==  Address 0x522d048 is 8 bytes inside a block of size 16 free'd
==13792==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13792==    by 0x108780: main (dynmem.c:27)
==13792==  Block was alloc'd at
==13792==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13792==    by 0x1086EB: main (dynmem.c:15)
==13792== 
==13792== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 

我是一个完整的 C 新手,无法理解这些泄漏的来源以及我需要做些什么来纠正它们。 非常感谢帮助。

本声明

typedef struct {
struct chain *next;       
int contents;  } chain; 

是不正确的。 声明了两个结构。 第一个是未命名的结构

typedef struct {

为其分配了 typedef 名称chain 在这个未命名的结构中,还声明了一个结构struct chain ,用作数据成员next的说明符。

struct chain *next;       

所以chain *struct chain *类型的指针不兼容。

该结构必须声明为

typedef struct chain {
    struct chain *next;       
    int contents;  
} chain; 

在此代码段中

list = malloc(sizeof(chain));     
p = list;     

for(index=0;index<10;index++) {       
    (*p).contents = index;       
    (*p).next = malloc(sizeof(chain));       
    p = (*p).next; 
   } ;  

您分配了类型链的 11 个对象。 但是在此代码段中

while (index < 9) { 
    printf("cell # %d: %d\n",index,(*p).contents);       
    p = (*p).next;       
    free(pointer);       
    pointer = p;       
    index++; 
  } ; 

您只释放了类型链的 9 个动态分配的对象。

此外,指针列表的值没有改变。 所以程序在这个语句中调用了未定义的行为

printf("First cell: %d\n",(*list).contents); 

例如,程序可以按以下方式编写。

#include <stdlib.h>
#include <stdio.h>

typedef struct chain
{
    struct chain *next;       
    int contents;  
} chain; 

int main( void )  
{
    const int N = 10;

    chain *list = NULL;

    chain **current = &list;

    for ( int i = 0; i < N; i++ ) 
    {
        *current = malloc( sizeof( chain ) );
        ( *current )->contents = i;       
        ( *current )->next = NULL;       
        current = &( *current )->next;
    } ;     

    for ( int i = 0; i < N - 1; i++ )
    {
        printf( "cell # %d: %d\n", i,  list->contents ); 

        chain *tmp = list;
        list = list->next;
        free( tmp );       
     }

    printf( "First cell: %d\n", list->contents );

    while ( list != NULL )
    {
        chain *tmp = list;
        list = list->next;
        free( tmp );
    }

    return 0;  
} 

程序 output 是

cell # 0: 0
cell # 1: 1
cell # 2: 2
cell # 3: 3
cell # 4: 4
cell # 5: 5
cell # 6: 6
cell # 7: 7
cell # 8: 8
First cell: 9
①如果本文未解决您的问题,请点击查看与本文相关的问题
②如果本文未解决您的问题,请向程序员专用AI小助手提问
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM