为什么我会遇到分段错误?

时间:2013-05-16 17:38:26

标签: c segmentation-fault undefined-behavior

我正在尝试学习如何在 C 中使用结构和链接列表,但我真的不明白为什么以下代码会给我分段错误:

我有3个名为 list.h,operations.c和main.c 的文件。在文件 list.h

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

typedef char DATA;

struct linked_list {
    DATA                   d;
    struct linked_list *next;
};

typedef struct linked_list ELEMENT;
typedef ELEMENT              *LINK;

LINK string_to_list(char s[]);
void print_list(LINK);

文件 operations.c

#include "list.h"

LINK string_to_list(char s[]){
    LINK head = NULL;

    if (s[0]) {
        ELEMENT c = {s[0], NULL};
        c.next = string_to_list(s+1);
        head = &c;
    }

    return head;
}

void print_list(LINK head) {
    if(head != NULL){
        putchar(head -> d);
        print_list(head -> next);
    } else {
        putchar('\n');
    }
}

文件 main.c

#include "list.h"

int main(void) {
    LINK head = string_to_list("wtf");
    print_list(head);
    return 0;
}

3 个答案:

答案 0 :(得分:4)

if (s[0]) {
    ELEMENT c = {s[0], NULL};        // Allocate space for struct on the stack
    c.next = string_to_list(s+1);
    head = &c;                       // Save the address to head
}  // <-- poof, c goes out of scope and is deallocated from the stack

return head; // <-- return address of deallocated object

答案 1 :(得分:2)

string_to_list中,您正在 if语句中获取本地变量的地址(大多数现代实现中的存储在堆栈):< / p>

head = &c;

然后在此处返回该地址:

return head;

if语句结束后,变量c将不再存在,这是undefined behaviorC99 draft standard部分6.2.4 对象的存储持续时间 2 表示:

  

[...]如果某个对象在其生命周期之外被引用,则该行为未定义。[...]

答案 2 :(得分:2)

if (s[0]) {
--->    ELEMENT c = {s[0], NULL};
    c.next = string_to_list(s+1);
    head = &c;
}

return head;

是本地记忆。一旦离开函数(甚至代码块),该内存就会被释放并且不再有效。你需要malloc()它,或者为这个函数传递一些内存来使它超出这个功能。