我正在尝试学习如何在 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;
}
答案 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 behavior。 C99 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()
它,或者为这个函数传递一些内存来使它超出这个功能。