c - 段错误,尽管代码从未执行?

标签 c pointers crash linked-list segmentation-fault

我刚刚开始学习 C,正在研究链表的简单实现。当我尝试打印我的 list 时,我意识到一些奇怪的事情。即使该代码从未执行过,我也会在部分代码中出现段错误。怎么会这样?

据我所知,while 循环永远不会执行,因为下一个指针没有指向任何东西。我在想,也许在评估 while 循环时,它可能会导致它指向导致段错误的东西,但奇怪的是,如果您删除行 root = root->next 它执行得很好(没有任何错误)。即使如此,它也永远不会进入 while 循环。那么,如果一行代码(root = root->next)从未执行过,它怎么会导致错误呢?代码编译得很好。我是否在某个地方犯了一个简单的错误?

我知道这几乎不是链表的正确实现,它是为了学习目的而设计的。

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

struct linkedlist   {
    int value;
    struct linkedlist * next;
};

typedef struct linkedlist item;

int main(int argc, char **argv) {
    item * root;
    item * current;

    root = malloc(sizeof(item));
    root->value = 500;

    int i;
    for(i = 0; i <= 20; i++)    {
        current->next = malloc(sizeof(item));
        current = current->next;
        current->value = i;
    }

    while(root->next != 0)  {
        //This is never executed
        printf("[%d]\n", root->value);
        //the line below does cause the segmentation error
        //but how can this affect anything at all if this is never executed?
        root = root->next;
    }
    return 0;
}

最佳答案

第一行current->next是取消引用未初始化的指针。您可能忘记在循环之前将 current 初始化为 root。取消引用未初始化的指针是未定义行为 (UB),这意味着任何事情都可能发生。实际上,未初始化的变量将具有与存储在其内存位置的任何内容相对应的值。因此,未初始化的指针将被设置为某个半随机地址,并且要么指向内存中的一些半随机内容(可能是其他程序变量),要么无效。

在 while 循环测试 root->next 的条件中取消引用另一个未初始化的指针。一般来说,您应该确保每个列表项(包括 root)的 next 字段设置为 0,否则您将不会'无法检测到链表的末尾(再次未初始化的指针,因此再次UB,实际上该值可能与0不同)。

纠正代码中此类问题的建议:

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

struct linkedlist   {
    int value;
    struct linkedlist * next;
};

typedef struct linkedlist item;

int main(int argc, char **argv) {
    item * root;
    item * current;

    root = malloc(sizeof(item));
    root->value = 500;
    root->next = 0;

    current = root;

    int i;
    for(i = 0; i <= 20; i++)    {
        current->next = malloc(sizeof(item));
        current = current->next;
        current->value = i;
        current->next = 0;
    }

    while(root->next != 0)  {
        printf("[%d]\n", root->value);
        root = root->next;
    }
    return 0;
}

关于c - 段错误,尽管代码从未执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21296104/

相关文章:

更改字符串的大小写

c - 我们应该在信号处理程序中使用 perror

c - 警告 : iteration 5u invokes undefined behavior [-Waggressive-loop-optimizations]

c - `char *`和 `int *`之间的不同语义

android - Android/Java:如何实现AsyncTask?

ios - 在 iphone ios 7.0.4 中,启动应用程序时应用程序崩溃

c - 像访问单个数组一样访问结构成员?

c - 为什么指向函数指针的指针是8字节?

c# - 使用 ref 参数委托(delegate)

iPhone 在呈现模态视图 Controller 时崩溃