底部的main
中发生错误。
添加节点-数据:1
分段故障(核心转储)
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct Node
{
int data;
struct Node* prev;
struct Node* next;
}Node;
typedef struct List
{
Node* head;
Node* tail;
int count;
}List;
void InitList(List *list)
{
(list) = (List*)malloc(sizeof(List));
(list) -> head = NULL;
(list) -> tail = NULL;
(list) -> count = 0;
}
Node* CreateNode(int data)
{
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> prev = NULL;
node -> next = NULL;
return node;
}
void AddNode(List *list, Node* node)
{
if (!(list) || !node) return;
printf("Add Node - data : %dn", node -> data);
if ((list) -> count == 0)
{
(list) -> head = (list) -> tail = node;
node -> next = node -> prev = node;
}
else
{
node -> prev = (list) -> tail;
node -> next = node -> prev = node;
(list) -> tail -> next = node;
(list) -> head -> prev = node;
(list) -> tail = node;
}
(list) -> count++;
}
int main()
{
List list;
InitList(&list);
for (int i = 1; i < 5; i++)
AddNode(&list, CreateNode(i));
return 0;
}
这是一个关于C中电路双链接列表的代码。存在原始代码,我对其进行了修改,以了解为什么使用原始多指针。在main中调用AddNode(&list, CreateNode(i)
时直接发生错误。
(这里是原始代码的所在地,但不是英语)(https://huiyu.tistory.com/entry/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EB%8F%99%EC%A0%81%ED%95%A0%EB%8B%B9%EC%9D%84-%EC%9A%A9%ED%9C-%EC%97%B0%EA%B2%B0-%EB%A6%AC%EC%8A%A4%ED%8A%B8链表-EA%B5%AC%ED%98%84)
我预计它会起作用,因为在main
中,我声明了List list
,然后调用了InitList(&list)
。我以为这是引用调用,但可能不是
我试了一些测试,然后发现了一些问题。
- 我用列表类型list的地址调用
InitList
- 我希望该列表会被初始化,因为我给出了带有地址的参数
- 但当我打印
list
的count
的值时,它是垃圾值。(当我在InitList
中打印时,那是0) - 因此,当列表的
head
和tail
为NULL
(通过assert
找到)时,count
不为零,则发生错误
我无法理解为什么它不是通过引用调用,以及为什么需要多个指针。
请记住,函数的参数是通过值传递的。这意味着调用中的值被复制到函数的局部参数变量中。所有函数都有一个副本,它独立于调用中的原始变量或值。这意味着
(list) = (List*)malloc(sizeof(List));
在您的InitList
中根本不起作用,您只能修改本地list
变量。main
函数中的原始值&list
不会被修改。事实上,它不能。
这意味着您在InitList
函数中初始化的List
结构对象与main
函数中的对象不同。main
函数中的List
结构对象将保持未初始化状态。
您似乎听说过,通过向变量传递指针来模拟逐引用传递。但您忽略了一个重要的点:指针本身仍将按值传递。
问题的简单解决方案是简单地从InitList
函数中删除该赋值:
void InitList(List *list)
{
// list is already pointing to a properly allocated List structure
(list) -> head = NULL;
(list) -> tail = NULL;
(list) -> count = 0;
}
其他可选方案是将main
函数中的list
更改为指针,并将指针传递给该指针,这意味着InitList
必须采用List **list
参数或者您将list
定义为一个普通的局部变量,进行分配,然后返回指针。
当您编写列表时=>现在,当您在initlist()函数中再次执行malloc操作时,内存已经分配给了list对象,然后将指针指向一个新的内存位置,因此,以前指向list对象位置的指针现在指向其他地址位置。因此,您在initlist函数中对此指针所做的所有更改都会反映到存储在某个新地址位置(而不是列表对象)的结构对象中。
解决方案:与其他答案中提到的相同,即删除initlist函数中的malloc行。
或者您可以将malloc()留在InitList函数中,但您只需要将"list"变量定义为main()函数中list结构的指针:
List *list = NULL;