SEGV:将节点添加到链表末尾时大小为 8 的无效写入

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 开头的列表后面添加一个节点。

仅供参考: 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;,这让我觉得它来自于我分配(或没有?)我对 "next" 的记忆的方式节点,但我找不到问题所在。

感谢任何帮助。

以下代码片段

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 是列表的初始节点。

通常为指针创建这样的别名不是一个好主意。很难理解您的代码。

此外,如果您要将节点附加到单向链表的末尾,那么您应该声明一个双向单向链表。对于单边单向链表,此函数效率低下。

您正在分配 sizeof(list_t),这是一个指针。你必须做:

malloc(sizeof(node_t));

正是这种隐藏 * 的卑鄙想法的结果。

第二个问题:当 headNULL 时,您将空指针传递给具有 &head 的函数。显然 next 位于偏移量 0x08。因为 tmp0tmp->next0 + 0x08。可以使用 head = malloc(sizeof(node_t)).

进行快速检查

正如其他人所说,将 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);
}