2009-01-11 42 views
2

我承認是一個C型的新手,但這讓我難住了。我正在練習了鏈表的實現,而且我通過簡單地增加一個變量來split_node功能得到段錯誤:Segfault從添加變量

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

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 -o -Wall名單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 <Address 0x8b000000 out of bounds>}) 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 

爲什麼添加變量定義會導致段錯誤?它似乎是粉碎新創建的節點的內容指針。我很困惑;任何幫助?

回答

15

您需要動態分配節點(使用malloc)。

正如你所見,你的新節點是在棧上聲明的。當拆分函數返回時,該新節點不再有效的內存。

添加變量會導致段錯誤,因爲該變量會改變堆棧的佈局,導致函數返回時的行爲稍有不同。

0

嘗試設置節點子屬性爲NULL,C不會自動地零出內存中,因此它看起來像你的孩子可能有垃圾(或您可以使用釋放calloc代替的malloc)。 SoapBox的答案也是正確的。

0

Valgrind是一個偉大的工具,以幫助找到這些類型的問題。你可以做「的valgrind myappname」在命令行中,它會給你這些類型的錯誤的詳細信息。