【问题标题】:C- Memory leak, why?C-内存泄漏,为什么?
【发布时间】:2016-06-29 13:24:24
【问题描述】:

我用valgrind我发现了以下函数告诉我:

  LEAK SUMMARY:
 ==3120==    definitely lost: 7,968 bytes in 377 blocks
 ==3120==    indirectly lost: 0 bytes in 0 blocks
 ==3120==      possibly lost: 1,904 bytes in 7 blocks
 ==3120==    still reachable: 224 bytes in 7 blocks
 ==3120==         suppressed: 0 bytes in 0 blocks
 ==3120== Reachable blocks (those to which a pointer was found) are not shown.
 ==3120== To see them, rerun with: --leak-check=full --show-leak-kinds=all
 ==3120== 
 ==3120== For counts of detected and suppressed errors, rerun with: -v
 ==3120== Use --track-origins=yes to see where uninitialised values come from
 ==3120== ERROR SUMMARY: 644 errors from 6 contexts (suppressed: 0 from 0)

功能是:

 void put(message_t dati, op_t *err){
     message_data_t payload=dati.data;
     message_t *key1=malloc(sizeof(message_t));
    *key1=dati.hdr;
     message_data_t *malldati=(message_data_t *)malloc(sizeof(message_data_t));
     malldati->len=payload.len;
     malldati->buf=payload.buf;
     if((icl_hash_insert(hash,(void *)&key1->key,malldati))==NULL){
         *err=13;
         free(chiave);
     }else{

          *err=11;
       }
  }

如果我在 else 中添加 free 程序将无法运行。

 void update(message_t dati, op_t *err){

     message_data_t *exist;
     message_data_t *payload=(message_data_t *) malloc(sizeof(message_data_t));
     payload=&dati.data;
     message_hdr_t key1=dati.hdr;

     exist=icl_hash_find(hash, &key1.key);

     if(exist == NULL){
         *err=20;
     }else{
        if(exist->len!=payload->len){
            *err=19;

         }else{
            exist=payload;
            *err=11;

         }
    }
 }


prototypes icl_hash_insert icl_hash_find and functions are:

icl_entry_t * icl_hash_insert(icl_hash_t *, void*, void *);

void * icl_hash_find(icl_hash_t *, void* );

问题出在 key1 (put) 和 payload (update) 我该如何修复代码? 感谢您的帮助!

更新:感谢您的回答,现在我有另一个由线程引起的内存泄漏。 Valgrind举报:

 ==6111== HEAP SUMMARY:
 ==6111==     in use at exit: 1,904 bytes in 7 blocks
 ==6111==   total heap usage: 1,168 allocs, 1,161 frees, 8,042,496 bytes allocated
 ==6111== 
 ==6111== Thread 1:
 ==6111== 1,904 bytes in 7 blocks are possibly lost in loss record 1 of 1
 ==6111==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
 ==6111==    by 0x40136D4: allocate_dtv (dl-tls.c:322)
 ==6111==    by 0x40136D4: _dl_allocate_tls (dl-tls.c:539)
 ==6111==    by 0x4E422AE: allocate_stack (allocatestack.c:588)
 ==6111==    by 0x4E422AE: pthread_create@@GLIBC_2.2.5 (pthread_create.c:539)
 ==6111==    by 0x40243D: main (membox.c:642)
 ==6111== 
 ==6111== LEAK SUMMARY:
 ==6111==    definitely lost: 0 bytes in 0 blocks
 ==6111==    indirectly lost: 0 bytes in 0 blocks
 ==6111==      possibly lost: 1,904 bytes in 7 blocks
 ==6111==    still reachable: 0 bytes in 0 blocks
 ==6111==         suppressed: 0 bytes in 0 blocks
 ==6111== 
 ==6111== For counts of detected and suppressed errors, rerun with: -v
 ==6111== Use --track-origins=yes to see where uninitialised values come from
 ==6111== ERROR SUMMARY: 641 errors from 3 contexts (suppressed: 0 from 0)

有什么问题?

【问题讨论】:

  • update function 中执行payload=&dati.data; 的那一刻,您丢失了为payload 分配的内存。
  • 一目了然,您的整个程序看起来就像一个大内存泄漏。如果你不释放你分配的东西,你就会得到泄漏......每次调用 malloc 都需要调用 free。

标签: c memory-leaks malloc free


【解决方案1】:

这让我很担心:

message_t *key1=malloc(sizeof(message_t));
*key1=dati.hdr;
...
if((icl_hash_insert(hash,(void *)&key1->key,malldati))==NULL){

您正在动态分配message_t 的全新对象,但只保存其中一个成员的地址。除非hdrmessage_t的第一个成员并且keyhdr的第一个成员,否则您保存在哈希中的地址与动态分配的地址相同目的。这意味着您以后将无法free 该内存。

基于这些 sn-ps,在我看来,您只想复制 key 以保存在哈希中,而不是整个 message_t 结构,就像这样:

T *key1 = malloc( sizeof *key1 ); // replace T with the actual key type
*key1 = dati.hdr.key;
...
if(( icl_hash_insert( hash, key1, malldati )) == NULL ){

我假设键和数据项在从哈希中删除时是freed。

【讨论】:

  • 感谢您的帮助!没有内存泄漏!
  • 但由于线程引起的其他内存泄漏,我已经编辑了帖子
【解决方案2】:

对于每个malloc,您需要free 一次。

put:您需要在put 结束之前free key1

update 中:您需要在updates 结束之前free payload

还有:payload=&dati.data; // you set payload to point to a new address, memory will be lost

void put(message_t dati, op_t *err){
     message_data_t payload=dati.data;
     message_t *key1=malloc(sizeof(message_t));
    *key1=dati.hdr;
     message_data_t *malldati=(message_data_t *)malloc(sizeof(message_data_t));
     malldati->len=payload.len;
     malldati->buf=payload.buf;
     if((icl_hash_insert(hash,(void *)&key1->key,malldati))==NULL){
         *err=13;
         free(chiave);
     }else{

          *err=11;
       }
       free(key1);
       free(malldati);
  }


void update(message_t dati, op_t *err){

     message_data_t *exist;
     message_data_t *payload=(message_data_t *) malloc(sizeof(message_data_t));
     payload=&dati.data; // you set payload to point to a new address, memory will be lost 
     message_hdr_t key1=dati.hdr;

     exist=icl_hash_find(hash, &key1.key);

     if(exist == NULL){
         *err=20;
     }else{
        if(exist->len!=payload->len){
            *err=19;

         }else{
            exist=payload;
            *err=11;

         }
    }
    free(payload);
 }

【讨论】:

  • 如果我在函数末尾使用 free 我有一个错误: 00bf8000-00c19000 rw-p 00000000 00:00 0 [heap] 7f4e3c000000-7f4e3c021000 rw-p 00000000 00:00 0 074e -7F4E4000000000- P 00000000 00:00 0 7F44021000-7F4E48021000-7F4E48000000 linux-gnu/libgcc_s.so.1 7f4e48d4d000-7f4e48f4c000 ---p 00016000 08:01 15205453 /lib/x86_64-linux-gnu/libgcc_s.so.1
  • 请说明您收到的是哪个函数和什么样的错误?
  • malldati 被添加到哈希结构中,所以他应该在函数退出之前 free 它。 key1 有点问题。
  • @JohnBode 谢谢。我刚刚更新了我的帖子。还发现代码有错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
相关资源
最近更新 更多