c中链表中的分段错误

时间:2013-06-03 07:52:28

标签: c linked-list

当我尝试打印出我的链表时,我遇到了段错误。有谁能解释为什么?我知道segfault意味着我正在访问我不应该访问的内存。我假设这意味着我没有正确设置我的指针。任何帮助都会很棒。我的代码......

#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;
}

4 个答案:

答案 0 :(得分:4)

此:

scanf("%s", &word);

是缓冲区溢出,因为%s将读取字符串,但您只有一个字符。这会调用未定义的行为;即使您只输入一个字符,scanf()也会在该字符后添加0终结符以生成正确的字符串。

更改word的声明:

char word[32];

使用显式大小扫描,以防止scanf()在缓冲区外写入​​:

scanf("%30s", word);

同时检查所有I / O和内存分配调用的返回值,因为它们可能会失败。

最后,don't cast the return value of malloc(), in C

答案 1 :(得分:0)

关于内存泄漏,我可以建议您使用以下代码修复它们:

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
}

这将在循环的每次迭代中释放已经打印的head

其他海报已经解决了其他问题。

答案 2 :(得分:0)

*head指针初始化为

item *curr=NULL, *head = NULL;

如果没有这个,if将不会执行,您将访问head节点的一些随机内存。用于打印链接列表的while循环可能无法终止并继续访问无效内存。

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

答案 3 :(得分:0)

你被scanf抓住了。首先,您希望阅读单个字符,其格式为%c - %s在跳过后读取下一个非空白字符序列任何领先的空白。使用%s会导致错误,因为它会覆盖内存。

但是,如果您将格式更改为%c,那么您的代码仍然无效,而且scanf会再次生效。对于大多数格式scanf将跳过前导空格,但在读取字符时执行此操作。因此,如果您运行代码,您将看到:

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

scanf第二次在10之后读取换行符word,而不是y,然后继续打印出您的列表 - 最后的10

要在字符之前跳过空白,请在格式字符串中添加空格,以便该行变为:

scanf(" %c", &word);

一次更改将允许您的代码工作,但您应该做更多的检查。 scanf将返回成功找到的项目数,您应该检查以确保用户确实输入了数字等等。例如,如果用户意外输入{{1},会发生什么两次:

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: 失败,返回scanf("%d", &temp),并且未将任何内容存入0。但是,由于您没有检查结果,程序会继续,然后下一个temp消耗第二个y

另请查看您的scanf(" %c", &word)声明 - 这根本不是必需的,您可以用两行代替整个if (head == NULL) / if ...锻炼。

HTH