2016-03-08 63 views
1

我遇到了在實現單向鏈表時看起來很奇怪的問題。我調用list_destroyer並將指針傳遞給列表的頭部,但是當方法返回時,傳遞的指針仍指向完整列表。我不相信我已經在任何地方傳遞了一個結構體。釋放c中單獨鏈接的列表

這裏是我的結構列表,typedef的

typedef struct list list_t 
struct list{ 
    void* datum; 
    list_t* next; 
}; 

這裏就是導致問題

void list_destroy(list_t *head){ 
    list_t *destroy = head; 
    while(head){ 
     //printf("%d \n", list_size(head)); 
     head = head->next; 
     free(destroy); 
     destroy = head; 
    } 
    //printf("%d \n", list_size(head)); 
    head = NULL; 
    //printf("%d \n", list_size(head)); 
} 

的list_size功能已被註釋掉了,因爲他們是沒有必要的代碼,但我使用它們來查看代碼的輸出。 printf輸出顯示大小正在減小。兩個printf圍繞着「head = NULL;」語句都打印一個零大小。這也可以通過gdb來確認。然而,當我有這個代碼(下面)調用list_destroy時,傳遞的指針是不變的。

int main(){ 
    list_t *test = NULL; 
    int a = 1; 
    int b = 2; 
    list_append(test,&a); 
    list_append(test,&b); 
    printf("%d \n", list_size(test)); 
    list_destroy(test); 
    printf("%d \n", list_size(test)); 
} 

我仍然得到printf的上方和list_destroy到兩個輸出2.我沒有任何地方初始化的新list_t下面,所以我不明白怎麼list_destroy後的printf將仍然輸出2,(尤其是當list_destroy內的printf說*傳入的list_t具有在最後一個大小爲0。

+1

,我不知道這是一個充分的解釋(我沒有看過你的代碼詳細)但釋放內存不會覆蓋它。 –

回答

3

但是在方法返回時,傳遞仍然指向的完整列表指針。

這是不正確的:當函數retu rns,指針指向過去的完整列表。很有可能,你的系統可以讓你不中斷地遍歷整個列表。但是,在調用後取消引用此指針是未定義的行爲,因此相同的代碼可能會在其他系統上崩潰。

該問題有一個名稱 - head成爲懸掛指針

解決這個問題很簡單 - 將指針傳遞指針,並且在完成時將其設置爲NULL

void list_destroy(list_t **headPtr){ 
    list_t *head = *headPtr; 
    list_t *destroy = head; 
    while(head){ 
     head = head->next; 
     free(destroy); 
     destroy = head; 
    } 
    *headPtr = NULL; 
} 
+0

這與我所擁有的真的不同嗎?你對* headPtr的使用等同於我的list_t *頭,不是嗎?我有一行「head = NULL;」在最後。所以指針不應該晃來晃去。我的思維過程在這裏錯了嗎? –

+0

@DrewKay在你的代碼中賦值'head = NULL'對傳入'list_destroy'的指針沒有影響,因爲指針是按值傳遞的。 'list_destroy'從'main'中獲得它自己的'test'的私有副本。可以隨意分配它, 'main'函數中的'test'將保持不變。我的修改通過指針傳遞指針,讓'list_destroy'內的賦值修改'main'函數的'test'指針。 – dasblinkenlight

+0

啊,謝謝。這就說得通了。但是,這是針對一個類的項目,實現需要list_destroy(list_t * head),所以我會給教授發郵件,看看是否有錯誤。 –