问题描述
我不知道我的问题是否还有其他线索,但如果有,我找不到。
问题是释放链表中现在未使用的单元格/节点。 我在当前状态下使用程序获得了我预测的确切泄漏量,但是我使用的 2 'free()' 似乎有点矫枉过正,IDE 已经警告我访问已释放的内存。 (我已经运行它并且 IDE 是正确的) 那么,我如何重写我的代码以实际释放它应该释放的 1 个单元格?
我的节点:
typedef struct node {
char val[2] ; //arrays (in this project of size 2)
struct node * next;
} node_t;
// removes the item at the given position from the list (starting counting from 0)
// memory leakage but idk how to free
node_t* remove_from_list(node_t *head,int index){
node_t *prev = make_list();
printf("prev:");
print_list(prev);
node_t *target = head;
printf("target:");
print_list(target);
// jumping to the location
while (index > 0){
*prev = *target;
target = target->next;
index--;
}
printf("after jump target:");
print_list(target);
printf("new prev:");
print_list(prev);
sleep(1);
//checking if last slot in list
if (is_list_empty(*target) == 2){ //true
printf("last in chain");
sleep(1);
if (is_list_empty(*prev) == 0){ //list of only 1 elem special case
printf("and (0)\n");
sleep(1);
free(prev);
free(target);
return NULL;
}
else{
printf("\n");
prev->next = NULL;
//free(target); <-- this doesnt work
// else c complains that memory used after free
return head;
}
}
//if first in list
if (is_list_empty(*prev) == 0){
printf("first in chain\n");
sleep(1);
head = head->next;
free(prev);
return head;
}
//else
printf("in the middle of chain\n");
*prev->next = *target->next;
printf("new list:\n");
print_list(head);
sleep(1);
//free(target); <-- this doesnt work
return head;
}
此状态下的控制台输出:
(e,f)->(c,d)->(a,b)->(x,y)->
prev:(0)->
target:(e,y)->
after jump target:(c,y)->
new prev:(e,y)->
in the middle of chain
new list:
(e,f)->(a,y)->
(e,y)->
=================================================================
==36817==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7f9b91de5279 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x56450617e2ea in make_list src/llist.c:11
#2 0x56450617e7db in remove_from_list src/llist.c:66
#3 0x56450617f16c in main src/main.c:45
#4 0x7f9b91a1db24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7f9b91de5279 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x56450617e2ea in make_list src/llist.c:11
#2 0x56450617e696 in add_to_list src/llist.c:56
#3 0x56450617f027 in main src/main.c:35
#4 0x7f9b91a1db24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
SUMMARY: AddressSanitizer: 32 byte(s) leaked in 2 allocation(s).
启用免费的控制台输出:
(e,y)->
=================================================================
==36962==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000050 at pc 0x5567843aacc0 bp 0x7ffc96b0e130 sp 0x7ffc96b0e120
READ of size 16 at 0x602000000050 thread T0
#0 0x5567843aacbf in print_list src/llist.c:125
#1 0x5567843ab194 in main src/main.c:46
#2 0x7f415e820b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
#3 0x5567843aa1fd in _start (/home/prog2/Project3/RaphDiener/pagerank+0x21fd)
0x602000000050 is located 0 bytes inside of 16-byte region [0x602000000050,0x602000000060)
freed by thread T0 here:
#0 0x7f415ebe7f19 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
#1 0x5567843aabba in remove_from_list src/llist.c:116
#2 0x5567843ab184 in main src/main.c:45
#3 0x7f415e820b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
prevIoUsly allocated by thread T0 here:
#0 0x7f415ebe8279 in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x5567843aa2ea in make_list src/llist.c:11
#2 0x5567843aa696 in add_to_list src/llist.c:56
#3 0x5567843ab0d1 in main src/main.c:39
#4 0x7f415e820b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
SUMMARY: AddressSanitizer: heap-use-after-free src/llist.c:125 in print_list
Shadow bytes around the buggy address:
0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00 00 fa fa 00 00 fa fa[fd]fd fa fa 00 00
0x0c047fff8010: fa fa 00 00 fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==36962==ABORTING
解决方法
函数定义不正确有冗余内存分配
node_t *prev = make_list();
(如果一个函数需要删除一些东西,为什么它会创建一些东西?!)可以调用未定义的行为
while (index > 0){
*prev = *target;
target = target->next;
index--;
}
(循环中没有检查target是否等于NULL),代码不清楚
if (is_list_empty(*target) == 2){ //true
(幻数 2 是什么意思?!代码的读者期望函数应该返回 1(真)或 0(假))
我将展示如何简单地实现该功能。 研究它无论如何,如果您想编写自己的函数定义,那么所提供的函数定义将对您有用。
int remove_from_list( node_t **head,size_t index )
{
while ( *head && index-- )
{
head = &( *head )->next;
}
int success = *head != NULL;
if ( success )
{
node_t *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
return success;
}
而且该函数至少可以像这样调用
remove_from_list( &head,index );