[英]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_t
是node_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));
正是這個低級想法隱藏*
。
第二個問題:當head
為NULL
,您將使用&head
將空指針傳遞給函數。 顯然, next
偏移量為0x08
。 因為tmp
為0
, tmp->next
為0 + 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.