C-内存泄漏,为什么?

C- Memory leak, why?

我发现 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)

有什么问题?

对于每个 malloc 你需要 free 一次。

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

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

另外: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);
 }

这让我担心:

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 该内存。

根据这些片段,在我看来您只想复制 key 以保存在哈希中,而不是整个 message_t 结构,像这样:

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

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