C-内存泄漏,为什么?

时间:2016-06-29 13:24:25

标签: c memory-leaks malloc free

我在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(更新)中 我如何修复代码? 谢谢你的帮助!

更新:感谢您的回答,现在我有另一个由线程引起的内存泄漏。 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)

有什么问题?

2 个答案:

答案 0 :(得分: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);
 }

答案 1 :(得分:0)

这让我很担心:

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那个记忆。

基于这些片段,在我看来,您似乎只想复制以保存在哈希中,而不是整个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 ){

我假设密钥和数据项从哈希中删除时为free d。