简体   繁体   English

c中链表期间的分段错误

[英]Segmentation Fault during linked list in c

I am getting a segfault when I try and print out my linked list. 尝试打印链接列表时出现段错误。 Can anyone explain why? 谁能解释为什么? I am aware a segfault means that I am accessing memory I am not supposed to. 我知道,segfault意味着我正在访问不应该访问的内存。 I am assuming this means I am not setting up my pointers right. 我假设这意味着我没有正确设置指针。 Any help would be great. 任何帮助都会很棒。 My code... 我的代码...

#include <stdio.h>
#include <stdlib.h>


struct node
{
    int val;
    struct node *next;             
}*head;

typedef struct node item;

int main() {

    item *curr, *head;

    head = NULL;

    char word = 'y';
    //int num[10];
    //int i = 0;

    while (word == 'y'){
    printf("Would you like to enter an integer? (y/n) ");
    scanf("%s", &word);

        if(word == 'y'){
            int temp = 0;
            printf("Enter an integer: ");
            scanf("%d", &temp);
            curr = (item *)malloc(sizeof(item));
            curr->val = temp;
            if (head == NULL){
                head = curr;
                head->next = NULL;
            }
            else {
            curr->next  = head;
            head = curr;
            }
        }
    }

    curr = head;

    while(curr != NULL) {
        printf("%d\n", curr->val); //seg fault happens here
        curr = curr->next ;
    }
    return 0;
}

This: 这个:

scanf("%s", &word);

is a buffer overflow, since %s will read a string , but you only have a single character. 是缓冲区溢出,因为%s将读取一个字符串 ,但是您只有一个字符。 This invokes undefined behavior; 这会引起未定义的行为; even if you enter just a single character, scanf() will add 0-termination after that character to make a proper string. 即使您仅输入一个字符, scanf()也会在该字符后添加0终止符以构成正确的字符串。

Change the declaration of word : 更改word的声明:

char word[32];

And scan with an explicit size, to prevent scanf() from writing outside the buffer: 并以明确的大小进行扫描,以防止scanf()在缓冲区外写入​​:

scanf("%30s", word);

Also check the return values of all I/O and memory allocation calls, since they can fail. 还要检查所有I / O和内存分配调用的返回值,因为它们可能会失败。

Finally, don't cast the return value of malloc() , in C . 最后, 不要在C中malloc()的返回值

Regarding the memory leaks, can I suggest you fix them with the following code: 关于内存泄漏,我是否可以建议您使用以下代码修复它们:

while(curr != NULL) {
    item* temp = curr; // store the current pointer
    printf("%d\n", curr->val);
    curr = curr->next ;
    free(temp); //free the current one now that curr points to the next
}

This frees the already printed head in each iteration of the loop. 这将在循环的每次迭代中释放已打印的head

The other issues are already addressed by other posters. 其他问题已经由其他张贴者解决。

Initialize the *head pointer as 初始化*head指针为

item *curr=NULL, *head = NULL;

without this, the if will not execute and you would access some random memory for head node. 否则, if将不会执行,您将访问head节点的一些随机内存。 The while loop for printing the linked list may not terminate and keep accessing invalid memory. 打印链接列表的while循环可能不会终止,并继续访问无效的内存。

if (head == NULL){ 
  ...
}

You have been caught out by scanf . 您已经被scanf First you wish to read a single character and the format for that is %c - %s reads the next non-blank sequence of characters after skipping any leading whitespace. 首先,您希望读取一个字符 ,其格式为%c %s 跳过任何前导空格读取下一个非空白字符序列。 Using %s causes the error, as it overwrites memory. 使用%s会导致错误,因为它会覆盖内存。

However if you change the format to %c your code still won't work, and it's scanf again. 但是,如果将格式更改为%c您的代码仍然无法使用,并且再次变为scanf For most formats scanf will skip leading whitespace, but it does not do this when reading characters. 对于大多数格式, scanf会跳过前导空格,但在读取字符时会这样做。 So if you run your code you will see this: 因此,如果您运行代码,将会看到以下内容:

Would you like to enter an integer? (y/n) y
Enter an integer: 10
Would you like to enter an integer? (y/n) 10

The second time around scanf has read the newline after the 10 into word , that is not a y , and then moved on to print out your list - the 10 at the end. scanf的第二次读取10word之后的换行符,即不是y ,然后继续打印输出列表-最后的10

To skip whitespace before a character you add a space into the format string, so the line becomes: 要在字符跳过空格请在格式字符串中添加一个空格,这样该行将变为:

scanf(" %c", &word);

That one change will allow your code to work but you should really do more checking. 这一更改将使您的代码能够正常工作,但您实际上应该进行更多检查。 scanf will return the number of items it successfully found, you should check that to make sure the user really did enter a number etc., etc. As an example here is what happens if the user accidentally enters y twice: scanf将返回成功找到的项目数,您应检查并确保用户确实输入了数字等。例如,如果用户不小心输入y两次,将发生以下情况:

Would you like to enter an integer? (y/n) y
Enter an integer: y
Would you like to enter an integer? (y/n) Enter an integer: 

What has happened here is scanf("%d", &temp) failed, returned 0 , and stored nothing into temp . 这里发生的事情是scanf("%d", &temp)失败,返回0 ,并且没有将任何内容存储到temp However as you did not check the result your program continues and then the second y is consumed by the next scanf(" %c", &word) . 但是,由于您没有检查结果,因此您的程序继续运行,然后第二个y由下一个scanf(" %c", &word)占用。

Also look at your if (head == NULL) statement - this is not really necessary at all, you can replace the whole if / else with just two lines... that is left as an exercise. 还要看看您的if (head == NULL)语句-根本不是必须的,您可以将整个if / else替换为仅两行...作为练习。

HTH HTH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM