2015-11-01 109 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调查代替了漂亮的错误消息。是的,调试器是另一种工具,需要一点时间来学习,但不是那么多,它会为您节省更多时间寻找错误。

相关问题