Segfault来自添加变量

我当然是一个直接的C新手,但这让我很难过。 我正在研究实践的链表实现,我只是通过向split_node函数添加一个变量来获得段错误:

#include  #include  #include  struct Node { struct Node *child; char *content; }; void print_list(struct Node node); void split_node(struct Node *node, int position); int main() { struct Node head, second, third; head.content = "first"; second.content = "second"; third.content = "i'm third"; head.child = &second; second.child = &third; print_list(head); split_node(&head, 3); print_list(head); return 0; } void print_list(struct Node node) { printf("%s\n", node.content); if(node.child) print_list(*node.child); } /* Split node into two nodes, with the first position characters of the node's content remaining with node, and the remainder being copied to the new node. (It doesn't yet truncate the first node's string, but does do the copy.) */ void split_node(struct Node *node, int position) { if(position >= strlen((*node).content)) return; struct Node newNode; newNode.child = (*node).child; (*node).child = &newNode; int length = (strlen((*node).content) - position); newNode.content = malloc(sizeof(char) * (length + 1)); strncpy(newNode.content, (*node).content + sizeof(char) * position, length); newNode.content[length] = '\0'; //int foo; } 

这段代码编译(gcc -Wall -o list list.c)并且运行正常:

 $ ./list first second i'm third first st second i'm third 

但是如果我在split_node结束时取消注释int foo ,编译并运行,我得到:

 $ ./list first second i'm third first st Segmentation fault 

gdb给了我这个回溯:

 #0 0x91d6ae70 in strlen () #1 0x91dd3126 in puts () #2 0x00001f21 in print_list (node={child = 0xbcec815b, content = 0x8b000000 
}) at list.c:41 #3 0x00001f3c in print_list (node={child = 0x8fe0154b, content = 0x1ff6 "i'm third"}) at list.c:42 #4 0x00001f3c in print_list (node={child = 0xbffff568, content = 0x1fef "second"}) at list.c:42 #5 0x00001f3c in print_list (node={child = 0xbffff570, content = 0x1fe9 "first"}) at list.c:42 #6 0x00001ee0 in main () at list.c:33

为什么添加变量定义会导致段错误? 它似乎粉碎了新创建的节点的内容指针。 我糊涂了; 任何帮助?

您需要动态分配节点(使用malloc)。

正如您所拥有的那样,您的新节点将在堆栈中声明。 当split函数返回时,该新节点不再是有效内存。

添加变量会导致段错误,因为该变量会更改堆栈的布局,从而导致函数返回时的行为略有不同。

尝试将Nodes子属性设置为NULL,C不会自动将内存清零,因此看起来你的孩子可能有垃圾(或者你可以使用calloc而不是malloc)。 SoapBox的答案也是正确的。

Valgrind是一个很好的工具,可以帮助找到这些类型的问题。 您可以从命令行执行“valgrind myappname”,它将为您提供有关这些类型错误的详细信息。