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
的全新对象,但只保存其中一个成员的地址。除非 hdr
是 message_t
的第一个成员并且 key
是 hdr
的第一个成员,否则您保存在哈希中的地址是 而不是 与动态分配对象的地址相同。这意味着您以后将无法 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 ){
我假设键和数据项在从散列中删除时是 free
d。
我发现 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
的全新对象,但只保存其中一个成员的地址。除非 hdr
是 message_t
的第一个成员并且 key
是 hdr
的第一个成员,否则您保存在哈希中的地址是 而不是 与动态分配对象的地址相同。这意味着您以后将无法 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 ){
我假设键和数据项在从散列中删除时是 free
d。