in Programming ~ read.

從愚蠢的錯誤學習

記錄一下今天犯的愚蠢錯誤,先來看看錯誤的程式碼:

輸入檔內容:

3
4 4 4
5 5 5
1 2 3
程式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include
usingnamespace std;

int main(int argc, constchar*argv[]){
    int n =0;
    int weight[n][n];
    int dis[n];
    int parent[n];
    bool visited[n];

    cin>> n;
    for(int i =0; i < n;++i){
        for(int j =0; j < n;++j){
            int w =0;
            cin>> w;
            weight[i][j]= w;
        }
    }
    for(int i =0; i < n;++i){
        for(int j =0; j < n;++j){
            cout<< weight[i][j]<<" ";
        }
        cout<< endl;
    }
}

最後的輸出竟然是:

3
1 2 3
1 2 3
1 2 3
一開始猜想可能是 for 迴圈中打錯字或是忘記 ++ 之類的,甚至還重寫了一個檔案來 diff,過了許久才發現這愚蠢的 bug:
在還沒有讀取到 stdin 的數值之前,我就拿 n 來宣告了所有的陣列大小!

不過最奇妙的是,這個是不會產生 segmentation fault 的!而且還可以順利列印出數值(雖然是錯的),於是我加了以下程式列印出記憶體位址與大小:

    printf("weight addr: %x\n", &weight[1]);
    printf("weight size: %u\n", sizeof(weight));
    printf("dis addr: %x\n", &dis);
    printf("dis size: %u\n", sizeof(dis));
    printf("parent addr: %x\n", &parent);
    printf("parent size: %u\n", sizeof(parent));
    printf("visited addr: %x\n", &visited);
    printf("visited size: %u\n", sizeof(visited));
輸出結果如下:

weight addr: bfffe6b0
weight size: 0
dis addr: bfffe6a0
dis size: 0
parent addr: bfffe690
parent size: 0
visited addr: bfffe680
visited size: 0
因為堆疊由記憶體位址高往低放,所以列印出來的位址是遞減的,比較特別的是為了驗證奇怪的輸出結果,上面程式是選擇列印 weight[1] 的位址而不是 weight。因此我們可以得出結論,只要是宣告為陣列,即使大小為零,編譯器還是會為這些陣列保留最小的固定空間,在我電腦上的情況是保留 16 bytes。

comments powered by Disqus