2014-01-22 13 views
2

我刚刚开始学习C并正在研究链接列表的简单实现。当我尝试打印我的清单时,我意识到一些奇特的东西。即使代码从未执行,我也会在代码的一部分发生分割错误。怎么会这样?分割错误,尽管代码从未执行?

据我所知,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; 
} 

回答

3

current->next第一行是访问一个未初始化的指针,你可能忘了循环前初始化currentroot。Derefencing未初始化的指针是未定义的行为(UB),这意味着任何事情都可能发生,实际上,未初始化的变量将具有与任何内容相对应的值s被存储在他们的记忆位置。因此,一个未初始化的指针将被设置为某个半随机地址,并将指向内存中的一些半随机内容(可能还有其他程序变量)或无效。

在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; 
} 
+0

但是,如果我取消对该行的root =根 - >下一步;并在最后输入一个prinf语句而不会崩溃。 –

+2

root-> next也不会在while循环之前初始化。 – OldProgrammer

+0

@OldProgrammer我可以检查while循环吗? while(root-> next!= NULL)? –