[英]Linked List making segmentation fault
Below I have made a simple Linked List in C. The code is currently producing a segmentation fault which I find odd because I was copying an example from our current book. 下面,我在C语言中创建了一个简单的链表。该代码当前正在产生一个分段错误,由于我要从当前书中复制一个示例,因此我觉得很奇怪。 The only thing I did to the code was put the code into the method "addToList".
我对代码所做的唯一一件事就是将代码放入“ addToList”方法中。 I'm aware the segmentation fault is coming from the method addToList but I do not know where I made a mistake.
我知道细分错误来自方法addToList,但我不知道在哪里出错。
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} Node;
void addToList(Node *, int);
void printList(Node *);
void main() {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
printf("Enter an integer: ");
x = scanf("%d");
addToList(head, x);
}
printList(head);
}
void addToList(Node *head, int val) {
Node *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(Node));
current->next->val = val;
current->next->next = NULL;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("\n");
}
Any help with telling me what is wrong or where I'm making the mistake would be greatly appreciated. 如有任何关于告诉我什么地方出了问题或在哪里犯错的帮助,将不胜感激。
Look carefully at your code: 仔细看看您的代码:
int main(void) {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
...
addToList(head, x);
}
...
}
You are not initializing the memory, so head->val
and head->next
are not initialized. 您没有初始化内存,因此
head->val
和head->next
未初始化。 Because of that 因此
while (current->next != NULL) {
current = current->next;
}
will loop an undefined amount of times. 将循环不确定的时间。 The first
current->next
is most probably not NULL
, so current = current->next
get executed. 第一个
current->next
很可能不是NULL
,因此current = current->next
会被执行。 At that point current
is pointing to nowhere, hence the undefined behaviour which in your case leads to a segfault. 此时,
current
指向无处,因此未定义的行为会导致段错误。
You have to initialized the memory like this: 您必须像这样初始化内存:
Node *head = malloc(sizeof *head);
if(head == NULL)
// error handling
head->next = NULL;
But you could also use calloc
, which also sets the memory to 0, thus you don't have to initialize the values (in this case): 但是您也可以使用
calloc
,它将内存设置为0,因此不必初始化值(在这种情况下):
Node *head = calloc(1, sizeof *head);
if(head == NULL)
// error handling
You should always check for the return value of malloc
/ calloc
/ realloc
. 您应该始终检查
malloc
/ calloc
/ realloc
的返回值。
Also note that the signature of the main
function can be one of these: 另请注意,
main
函数的签名可以是以下之一:
int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);
edit 编辑
Another error I've noticed right now: 我现在注意到的另一个错误:
x = scanf("%d");
That's not how scanf
works. 那不是
scanf
工作方式。 You have to pass a pointer, scanf
saves the scanned value through the passed pointer. 您必须传递一个指针,
scanf
通过传递的指针保存扫描的值。 scanf
returns the number of matched values on success, in this case, success would be 1: scanf
成功返回匹配值的数目,在这种情况下,成功将是1:
int num;
int ret = scanf("%d", &num);
if(ret != 1)
{
fprintf(stderr, "Could not read value from the user\n");
continue; // to contiune looping
// you could also do a break; and stop the looping, or
// exit(1), etc.
}
// error with scanf
Also don't use the same variable x
for the loop iteration and user input, otherwise you are messing with the loop. 另外,不要在循环迭代和用户输入中使用相同的变量
x
,否则会弄乱循环。
edit 编辑
User user3629249 wrote in the comment
用户user3629249在评论中写道
good information, however the result will be the first entry in the linked list will contain garbage.
好信息,但是结果将是链接列表中的第一个条目将包含垃圾。 Better to declare head via:
Node *head = NULL
;最好通过以下方式声明head:
Node *head = NULL
; and the functionaddToList()
check for NULL and proceed accordingly.然后函数
addToList()
检查是否为NULL并继续进行相应的操作。
That's right, the head
element doesn't save any number in this way. 没错,
head
元素不会以这种方式保存任何数字。
Option 1: double pointer 选项1:双指针
Here addToList
receives a double pointer. 在这里,
addToList
接收一个双指针。 The initialization of head
occurs when *head
points to NULL
. 初始化
head
时发生*head
指向NULL
。 The function allocates memory for it, initializes the memory, saves the value and returns. 该函数为其分配内存,初始化内存,保存值并返回。 In the concurrent calls of
addToList
*head
won't be NULL
, so addToList
looks for the end of the list. 在
addToList
的并发调用中, *head
不会为NULL
,因此addToList
查找列表的末尾。
I've made small changes in the way you do malloc
and realloc
. 我对
malloc
和realloc
的方式做了一些小的更改。 Also I added an implementation of freeList
which should be used to free the memory: 我还添加了
freeList
的实现,该实现应用于释放内存:
void addToList(Node **head, int val) {
if(head == NULL)
{
fprintf(stderr, "head cannot be NULL\n");
return;
}
if(*head == NULL)
{
*head = calloc(1, sizeof **head);
head[0]->val = val;
head[0]->next = NULL;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return;
current->next->val = val;
current->next->next = NULL;
}
int main(void)
{
int x;
Node *head = NULL;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
addToList(&head, val);
}
printList(head);
freeList(head);
return 0;
}
void freeList(Node *head)
{
if(head == NULL)
return;
Node *current = head;
Node *next;
while(next = current->next)
{
free(current);
current = next;
}
free(current); // the last one
free(head);
}
Option 2: addToList
returns a pointer to the head 选项2:
addToList
返回指向头的指针
Here addToList
takes a pointer to the head. 在这里,
addToList
指向头部。 If it's NULL
, it allocates memory and initializes like in the shown above. 如果为
NULL
,它将分配内存并进行初始化,如上所示。 If head
is not NULL
, the functions looks for the last element and the returns the head
. 如果
head
不为NULL
,则函数将查找最后一个元素并返回head
。 On error the function returns NULL
. 错误时,函数返回
NULL
。
Node *addToList(Node *head, int val) {
if(head == NULL)
{
head = calloc(1, sizeof **head);
head->val = val;
head->next = NULL;
return head;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return NULL;
current->next->val = val;
current->next->next = NULL;
return head;
}
int main(void)
{
int x;
Node *head = NULL, *tmp;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
tmp = addToList(head, val);
if(tmp == NULL)
{
fprintf(stderr, "Not enough memory\n");
freeList(head);
return 1;
}
head = tmp;
}
printList(head);
freeList(head);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.