2012-07-08 135 views
0

我有以下的C程序。它的工作原理,當我有以下行,否則它給出了一個分段錯誤:C中的分段錯誤

printf("head(%p), last(%p), newnode(%p)\n", head, last, newnode); 

任何想法有什麼問題嗎?

這是我的整個程序。這是一個基本的循環隊列示例。

#include "stdio.h" 
#include "malloc.h" 

struct node { 
    int data; 
    struct node *next; 
}; 

typedef struct node NODE; 

void display(NODE *); 

int main(void) { 

    NODE *head, *last, *newnode = NULL; 
    int i = 5; 

    for (; i > 0; i--) { 
     newnode = (NODE *) malloc(sizeof(NODE)); 
     newnode->data = i*10; 
     newnode->next = NULL; 

     //printf("head(%p), last(%p), newnode(%p)\n", head, last, newnode); 


     if (head == NULL) { 
      head = newnode; 
      last = newnode; 
     } else { 
      last->next = newnode; 
      last = newnode; 
     } 

     last->next = head; 
    } 

    display(head); 

    return 1; 
} 

void display(NODE *head) { 

    NODE *temp = NULL; 
    temp = head; 

    printf("Elements --> "); 
    do { 
      printf("%d ", temp->data); 
      temp = temp->next; 
    } while (temp != head); 

    printf("\n"); 

} 

回答

7

你需要明確初始化headlastNULL也。

在你的宣言:

NODE *head, *last, *newnode = NULL; 

newnode被初始化爲NULL。因此,在後來的if/else中,您正在測試/分配給隨機存儲器。

做這樣的事情:

NODE *head, *last, *newnode; 
head = last = newnode = NULL; 

不能假設指針自動初始化爲NULL,即使它可能在某些系統上的情況。聲明爲static的變量是例外。始終將C中的變量初始化爲合理的值,特別是指針。

當您訪問垃圾內存時,您正在調用undefined behavior。當你這樣做時,你可能會觀察到不一致和令人困惑的結果。在你的情況下,加入printf似乎來解決這個問題。這會影響你的代碼行爲的原因是依賴於實現,並且 - 一旦你引入了未定義的行爲 - 超出了你的控制範圍。

+0

感謝。它工作得很好。你能解釋爲什麼在沒有printf()語句的情況下出現分段錯誤,並且它可以正常工作。另外,我認爲當我們聲明一個指針時,它會自動分配給NULL。這不正確嗎? – divinedragon 2012-07-08 19:02:25

+0

@divinedragon:當且僅當變量是全局變量(包括靜態變量)時,指針變量在程序啓動時的值爲NULL。局部變量取而代之的是「不確定的值」。對於'printf'沒有任何理由,這只是巧合。 – 2012-07-08 19:24:00

+0

@divinedragon - 幾年前,我驚訝地發現一個未初始化的指針在一個已發佈的產品中多年以來一直沒有引起任何問題,直到與該指針無關的其他東西被更改,暴露了未初始化的指針錯誤。出於愚蠢的好奇心,我拋棄了舊代碼(「工作」)版本的反彙編,並向後追溯,發現同一個堆棧位置一次用於本地指針變量,而在較早的時間點(IN A不同的功能)作爲別的東西,退出該功能時總是爲零(即「NULL」)。 – phonetagger 2012-07-09 00:17:32

2

你沒有初始化headlast

NODE *head, *last, *newnode = NULL; 

讓他們有任何垃圾位,他們被分配並且即使head設置不正確if (head == NULL)可能會失敗。初始化爲NULL

+0

謝謝。它工作得很好。你能解釋爲什麼在沒有printf()語句的情況下出現分段錯誤,並且它可以正常工作。另外,我認爲當我們聲明一個指針時,它會自動分配給NULL。這不正確嗎? – divinedragon 2012-07-08 19:06:14

+1

只有靜態變量被自動初始化。你的指針是自動變量,所以它們不會被初始化。至於爲什麼'printf'避免了崩潰,我不能說,這是未定義的行爲。 – 2012-07-08 19:13:55

3

lasthead未被初始化。您可以打開編譯器警告,這將幫助你:

$ gcc -O1 -Wall w.c -o we 
w.c: In function ‘main’: 
w.c:30:23: warning: ‘last’ may be used uninitialized in this function [-Wuninitialized] 
w.c:26:12: warning: ‘head’ may be used uninitialized in this function [-Wuninitialized] 

(請注意,GCC需要-O1-Wuninitialized工作。)

+0

謝謝。它工作得很好。你能解釋爲什麼在沒有printf()語句的情況下出現分段錯誤,並且它可以正常工作。另外,我認爲當我們聲明一個指針時,它會自動分配給NULL。這不正確嗎? – divinedragon 2012-07-08 19:05:31