2015-11-01 58 views
4

我正在爲我正在進行的C編程課程的實驗任務工作。我在我的本地Cygwin目錄中編寫了代碼,使用gcc對其進行編譯,生成的可執行文件完全按照我希望的方式工作,沒有任何錯誤。爲什麼gcc不能一致地編譯這段代碼?

當我將我的代碼複製到我的學校的UNIX服務器上並用gcc進行編譯時,我沒有收到任何錯誤,但是當我嘗試運行它時,沒有任何反應。

我試圖這樣做gcc 2darray.c -Wall -pedantic,這是返回什麼:

2darray.c: In function 'main': 
2darray.c:5:3: warning: missing braces around initializer [-Wmissing-braces] 
2darray.c:5:3: warning: (near initialization for 'M[0]') [-Wmissing-braces] 
2darray.c:5:24: warning: C++ style comments are not allowed in ISO C90 [enabled by default] 
2darray.c:5:24: warning: (this will be reported only once per input file) [enabled by default] 

的錯誤提一些關於初始化數組M,但我沒有看到我初始化的方式出現任何問題。下面的代碼我試圖編譯:

#include <stdio.h> 

int main(void) 
{ 
    int M[10][10] = {0}; // creating a 10x10 array and initializing it to 0 
    int i, j; // loop variables 
    int sum[10] = {0}; // creating an array to hold the sums of each column of 2d array M 

    for (i = 1; i < 10; i++) // assigning values to array M as specified in directions 
    { 
     for (j = i - 1; j < i; j++) 
     { 
      M[i][j] = -i; 
      M[i][j+1] = i; 
      M[i][j+2] = -i; 
     } 
    } 

    for (i = 0; i < 10; i++) // printing array M 
    { 
     for(j = 0; j < 10; j++) 
     { 
      printf("%3d", M[i][j]); 
     } 
     printf("\n"); 
    } 

    printf("\n"); 
    for (i = 0; i < 10; i++) // calculating sum of each column 
    { 
     for (j = 0; j < 10; j++) 
     { 
      sum[i] = M[j][i] + sum[i]; 
     } 
     printf("%3d", sum[i]); // printing array sum 
    } 

    return 0; 
} 

我試圖插入變量聲明和第一個for循環和打印語句之間的printf語句,所以也許不順心的事在我的循環?

如果相關,這裏的輸出看起來像從我的Cygwin的目錄,它應該喜歡什麼我在學校的UNIX目錄:

0 0 0 0 0 0 0 0 0 0 
-1 1 -1 0 0 0 0 0 0 0 
    0 -2 2 -2 0 0 0 0 0 0 
    0 0 -3 3 -3 0 0 0 0 0 
    0 0 0 -4 4 -4 0 0 0 0 
    0 0 0 0 -5 5 -5 0 0 0 
    0 0 0 0 0 -6 6 -6 0 0 
    0 0 0 0 0 0 -7 7 -7 0 
    0 0 0 0 0 0 0 -8 8 -8 
    0 0 0 0 0 0 0 0 -9 9 

-1 -1 -2 -3 -4 -5 -6 -7 -8 1 
+7

嘗試更改'int M [10] [10] = {0};'爲'int M [10] [10] = {{0}};' – user1969104

+0

感謝您的建議。它雖然沒有修復它。 – user10721

+4

我只是試圖解決警告。我仍然試圖理解你的問題。你可以更好地解釋'可執行文件不起作用'的含義。 – user1969104

回答

7

您所訪問的陣列M的排它的邊界之外,造成未定義的行爲。

for (i = 1; i < 10; i++) 
// i ranges from 1 to 9 
    { 
    for (j = i - 1; j < i; j++) 
    // j ranges from i-1 (0 when i==1) to i-1 (8 when i==9) 
    // Consider what happens when j==8 
     { 
     M[i][j] = -i;  // j == 8 
     M[i][j+1] = i;  // j == 9 
     M[i][j+2] = -i;  // j == 10, out of bounds 
     } 
    } 

當我看着你的代碼中,j+2指數打動了我作爲一個徹頭徹尾的越界訪問最有可能的地方。我複製你的程序,並添加一行:

 M[i][j] = -i; 
     M[i][j+1] = i; 
     if (j+2 >= 10) puts("OUT OF RANGE"); 
     M[i][j+2] = -i; 

當我運行程序時,它打印OUT OF RANGE

至於從gcc -Wall -pedantic得到的警告,它們並不是真正的問題。通過與-std=c99編譯,可以避免關於//評論的警告。 「失蹤大括號」警告是虛假的。用於嵌套數據結構的初始化程序中的嵌套花括號是可選的,並且{0}是用於將整個數據結構(數組,結構,聯合)初始化爲零的完美有效方式。 gcc的最新版本(特別是5.2.0)不會對此提出警告。

+0

好,但問題提前一步。 M的第二個索引可以高達9,所以當'j'爲9時,帶有'j + 1'的行是個問題。 – donjuedo

+0

不是真的我想。 9在範圍內,不是嗎? – Elyasin

+0

本身,9是好的。這是我提到的9 + 1場景。 – donjuedo

2

最近版本的clang和gcc附帶了一個工具,可以簡化這些問題。請始終使用它,它會爲您節省大量時間尋找錯誤。

$ gcc s.c -Wall -Wextra -fsanitize=undefined 
$ ./a.out 
s.c:15:15: runtime error: index 10 out of bounds for type 'int [10]' 
s.c:15:21: runtime error: store to address 0x7fff6c53f2c0 with insufficient space for an object of type 'int' 
0x7fff6c53f2c0: note: pointer points here 
09 00 00 00 e5 ef 74 8a 11 7f 00 00 08 00 00 00 09 00 00 00 b0 10 40 00 00 00 00 00 00 00 00 00 
      ^

顯然,cygwin的可能不支持libubsan呢,所以你可能需要-fsanitize-undefined-trap-on-error它用一個簡單的陷阱,然後你就可以用gdb調查代替了漂亮的錯誤消息。是的,調試器是另一種工具,需要一點時間來學習,但不是那麼多,它會爲您節省更多時間尋找錯誤。