2013-08-17 67 views
1

爲了學習,我正在編寫一個簡單的鏈表實現。我的鏈表包含node結構,其中包含一個int值和一個指向下一個節點的指針。當我運行我的代碼時,它會無休止地循環,即使它在到達空指針時應該終止。我究竟做錯了什麼?鏈接列表循環不休

#include <stdio.h> 

struct node { 
    int value; 
    struct node *next_node; 
}; 

struct node * add_node(struct node *parent, int value) 
{ 
    struct node child; 
    child.value = value; 
    child.next_node = NULL; 

    parent->next_node = &child; 
    return parent->next_node; 
} 

void print_all(struct node *root) 
{ 
    struct node *current = root; 

    while (current != NULL) { 
    printf("%d\n", current->value); 
    sleep(1); 
    current = current->next_node; 
    } 
} 


int main() 
{ 
    struct node root; 
    root.value = 3; 

    struct node *one; 
    one = add_node(&root, 5); 
    print_all(&root); 
} 
+0

你在調試器中經過了多久? – kfsone

回答

5

你的程序表現出不確定的行爲:你是一個指針設置爲這裏本地分配struct

struct node child; 
child.value = value; 
child.next_node = NULL; 

parent->next_node = &child; 
return parent->next_node; 

由於child是在棧上,返回父指着它會導致不確定的行爲。

你需要動態分配child,使其工作:

struct node *pchild = malloc(sizeof(struct node)); 
// In production code you check malloc result here... 
pchild->value = value; 
pchild->next_node = NULL; 

parent->next_node = pchild; 
return parent->next_node; 

現在你已經動態分配的內存,不要忘記調用free在每個鏈表來防止內存的動態分配節點泄漏。

+0

你能否進一步解釋你的最後一句話?另外,當我在'main()'函數中聲明'struct node root'時,是在本地分配了'root'還是可以在'main()'函數之外訪問? – fbonetti

+0

@fbonetti由於'main'是堆棧中的最後一個函數,因此您可以在任何情況下使用您在其中聲明的任何內容。需要在你用'malloc'分配的每個指針上調用'free'函數。您需要編寫一個類似於'print_all'的函數'free_all'來遍歷列表,並釋放它所看到的每個節點。請記住,釋放在'main'中分配的節點是非法的,所以你想調用'free_all(root.next)'。 – dasblinkenlight

4

add_node返回一個指向局部變量這立即超出範圍,並且可以由其它功能被重新使用。嘗試訪問print_all會導致未定義的行爲。在你的情況下,看起來地址被current指針重用,而root->next_node指向root

爲了解決這個問題,你應該在add_node

struct node * add_node(struct node *parent, int value) 
{ 
    struct node* child = malloc(sizeof(*child)); 
    if (child == NULL) { 
     return NULL; 
    } 
    child->value = value; 
    child->next_node = NULL; 

    parent->next_node = child; 
    return child; 
} 

分配內存爲新的節點,因爲這種動態分配的內存,您將需要以後調用free。請記住不要試圖釋放root,除非您將其更改爲使用malloc進行分配。