簡體   English   中英

SEGV:將節點添加到鏈表的末尾時,大小為8的invalig寫

[英]SEGV: invalig write of size 8 when adding a node to the end of a linked list

我有這個功能:

int  list_add_elem_at_back(list_t *front_ptr, double elem)
{
        list_t  item = malloc(sizeof(list_t));
        list_t  tmp = *front_ptr;

        if (item == NULL)
                return (0);
        item->value = elem;
        item->next = NULL;
        while (tmp != NULL)
                tmp = tmp->next;
        tmp->next = item;
        return (1);
}

應該從t_list *front_ptr開始將一個節點添加到列表的t_list *front_ptr

僅供參考: list_tnode_t *的別名。

執行它時,出現SegV崩潰,並且Valgrind日志如下:

==3814== Invalid write of size 8
==3814==    at 0x4006C1: list_add_elem_at_back (simple_list.c:63)
==3814==    by 0x400A83: populate_list (simple_list.c:181)
==3814==    by 0x400B5C: main (simple_list.c:202)
==3814==  Address 0x521f048 is 0 bytes after a block of size 8 alloc'd
==3814==    at 0x4C2FB6B: malloc (vg_replace_malloc.c:299)
==3814==    by 0x40067D: list_add_elem_at_back (simple_list.c:56)
==3814==    by 0x400A83: populate_list (simple_list.c:181)
==3814==    by 0x400B5C: main (simple_list.c:202)
==3814== 
==3814== Invalid write of size 8
==3814==    at 0x4006EF: list_add_elem_at_back (simple_list.c:66)
==3814==    by 0x400A83: populate_list (simple_list.c:181)
==3814==    by 0x400B5C: main (simple_list.c:202)
==3814==  Address 0x8 is not stack'd, malloc'd or (recently) free'd

第63和66行是item->next = NULL; tmp->next = item; ,這讓我認為它來自我為“下一個”節點分配(或沒有?)內存的方式,但是我無法找出問題所在。

任何幫助表示贊賞。

您正在分配sizeof(list_t) ,它是一個指針。 您必須做:

malloc(sizeof(node_t));

正是這個低級想法隱藏*

第二個問題:當headNULL ,您將使用&head將空指針傳遞給函數。 顯然, next偏移量為0x08 因為tmp0tmp->next0 + 0x08 可以使用head = malloc(sizeof(node_t))進行快速檢查。

以下代碼段

int  add_node(list_t *front_ptr, double elem)
{
        list_t  item = malloc(sizeof(list_t));
        ^^^^^^^^^^^^^                ^^^^^^

這是沒有意義的,因為分配了一個指針而不是類型為node_t的結構。

我想你是說

int  list_add_elem_at_back(list_t *front_ptr, double elem)
{
        list_t  item = malloc(sizeof(*list_t));
        int success = item != NULL;

        if ( success )
        {
            item->value = elem;
            item->next = NULL;

            while ( *front_ptr != NULL) front_ptr = &( *front_ptr )->next;

            *front_ptr = item;
        }

        return success;
}

該函數可以通過以下方式調用

list_add_elem_at_back( &head, value );

其中head是列表的初始節點。

通常,為指針創建別名是個壞主意。 很難理解您的代碼。

另外,如果要將節點附加到單鏈列表的末尾,則應聲明一個雙面單鏈列表。 對於單面單鏈列表,此功能效率不高。

正如有人說,這是一個非常糟糕的主意,混淆node_t *list_t


您的第一個錯誤是:

list_t  item = malloc(sizeof(list_t));

相當於

node_t *item = malloc(sizeof(node_t *));

您要分配的是指針的大小,而不是node_t實例的大小。

你應該有

node_t *item = malloc(sizeof(node_t));

第二個錯誤來自瀏覽列表的方式。

list_t tmp = *front_ptr;
while (tmp != NULL)
    tmp = tmp->next;
tmp->next = item;

當tmp為NULL時,您的while循環停止,這意味着下一行( tmp->next = item; )執行NULL->next = item; ,這當然是無效的。

另外,如果* front_ptr為NULL(例如,當您嘗試創建第一個元素時),它將跳過循環(這是正常的),並產生相同的問題。

這就是我要做的:

int  list_add_elem_at_back(node_t **front_ptr, double elem)
{
    node_t *item = malloc(sizeof(node_t));
    node_t *tmp;

    if (item == NULL) {
        return (0);
    }
    item->value = elem;
    item->next = NULL;

    if (*front_ptr == NULL) {
        *front_ptr = item;
    } else {
        tmp = *front_ptr;
        while (tmp->next != NULL)
            tmp = tmp->next;
        tmp->next = item;
    }
    return (1);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM