微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

链表实现 C

如何解决链表实现 C

我不知道我的问题是否还有其他线索,但如果有,我找不到。

问题是释放链表中现在未使用的单元格/节点。 我在当前状态下使用程序获得了我预测的确切泄漏量,但是我使用的 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 );

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。