1

我正在尝试学习如何在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);

文件操作.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;
}
4

3 回答 3

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
于 2013-05-16T17:41:28.900 回答
2
if (s[0]) {
--->    ELEMENT c = {s[0], NULL};
    c.next = string_to_list(s+1);
    head = &c;
}

return head;

是本地内存。一旦您离开函数(甚至代码块),该内存就会被释放并且不再有效。您需要malloc()它,或者传递一些内存供此功能使用,以使其超出此功能。

于 2013-05-16T17:42:55.173 回答
2

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

head = &c;

然后在此处返回该地址:

return head;

if 语句结束后变量c将不再存在,这是未定义的行为C99 标准草案标准部分第2段对象的存储持续时间说:6.2.4

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

于 2013-05-16T17:41:41.403 回答