2011-01-28 247 views
2

這會給儘管我還沒有分配的內存和已宣佈的指針結構中的兩個內部主指針結構

struct one 
    { 
    char x; 
    int y; 
    }; 

    struct two 
    { 
    char a; 
    struct one * ONE; 
    }; 

    main() 
    { 
    struct two *TWO; 
    scanf("%d",&TWO->ONE->y); 
    printf("%d\n",TWO->ONE->y); 
    } 

而是一個合適的輸出,當我宣佈一個指向兩個外側本體的結構之後我會得到分段錯,但爲什麼是我不前一種情況得到分段錯誤

struct one 
    { 
    char x; 
    int y; 
    }; 

    struct two 
    { 
    char a; 
    struct one * ONE; 
    }*TWO; 


    main() 
    { 
    scanf("%d",&TWO->ONE->y); 
    printf("%d\n",TWO->ONE->y); 
    } 
+0

比較兩個不正確的東西的目的是什麼? – DReJ 2011-01-28 07:10:23

+0

你使用什麼編譯器?在gcc(cygwin)下運行你的第一個程序給了我Segmentation Fault。 – pankajt 2011-01-28 07:16:14

回答

1

因爲你在做什麼是不確定的行爲。有時它似乎工作。這並不意味着你應該這樣做:-)

最可能的解釋是與變量初始化怎麼做。當堆棧指針遞減時,自動變量(在堆棧上)將得到堆棧上發生的任何垃圾。

變量以外的功能(如在第二種情況下)總是初始化爲零(用於指針類型空指針)。

這就是你的兩種情況之間的基本差異,但是,正如我所說的,第一個是偶然的工作純粹。

3

在這兩種情況下TWO指針struct two類型的對象。

在情況1中,指針是百搭的,可以指向任何地方。

在情況2下,指針爲NULL,因爲它是全局的。

但是,在這兩種情況下,它指向一個不指向有效struct two對象的指針。您的scanf中的代碼正在處理這個指針,就好像它指的是一個有效的對象。這導致未定義的行爲。

1

在聲明全局指針,它會被初始化爲零,所以生成的地址將是小的數字,可能是也可能不是您的系統上讀取。

當聲明一個自動指針時,它的初始值可能會更有趣。在這種情況下,無論運行時庫在調用main()之前在堆棧中的那一點留下了什麼,也可能是編譯器生成的棧幀設置代碼的剩餘值。它有可能是一個保存的堆棧指針或幀指針,如果使用小偏移量,這是一個有效的指針。

所以無論如何,在未初始化的指針確實有它的東西,和一個值導致的故障,而另一方面,現在,您的系統上,其實不然。

這就是,因爲分段故障是OS的機制而不是C語言的機制。

故障是基於塊的機制,分配給自己和其他程序的網頁一定數量的 - 這是每個幾個的K - 同時也保護了自己和其他程序的網頁,同時讓你的程序自由支配。您必須偏離塊上下文,或嘗試寫一個只讀頁面(即使是你的)來產生錯誤。簡單地打破語言規則不一定就夠了。操作系統很高興讓你的程序因爲它的狂野引用而行爲不端並行爲異常,只要它自己只讀寫(或破壞者)。