简体   繁体   English

为什么gcc不能一致地编译这段代码?

[英]Why is gcc not compiling this code consistently?

I'm working on a lab assignment for a C programming class I'm taking. 我正在为我正在参加的C编程课程做实验工作。 I wrote the code in my local Cygwin directory, compiled it with gcc , and the executable that is produced works exactly the way I want it to without any errors. 我在我的本地Cygwin目录中编写了代码,用gcc编译它, gcc的可执行文件完全按照我想要的方式工作而没有任何错误。

When I copy my code over to my school's UNIX server and compile it with gcc , I don't get any errors, but when I try to run it, nothing happens. 当我将代码复制到学校的UNIX服务器并使用gcc编译时,我没有收到任何错误,但是当我尝试运行它时,没有任何反应。

I tried doing gcc 2darray.c -Wall -pedantic and this is what was returned: 我尝试做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]

The errors mention something about initializing the array M , but I don't see any problems with the way I initialized it. 这些错误提到了有关初始化数组M一些内容,但我没有看到我初始化它的方式有任何问题。 Here's the code I'm trying to compile: 这是我正在尝试编译的代码:

#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;
}

I tried inserting a printf statement between the variable declarations and the first for loop and the statement printed, so maybe something goes wrong in my loops? 我尝试在变量声明和第一个for循环和打印的语句之间插入一个printf语句,所以我的循环中可能出现问题?

If relevant, here's what the output looks like from my Cygwin directory and what it should like in my school's UNIX directory: 如果相关,这是我的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

You're accessing a row of the array M outside its bounds, causing undefined behavior. 您正在访问其边界外的数组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
      }
  }

When I looked at your code, the j+2 index struck me as the most likely place for an out-of-bounds access. 当我查看你的代码时, j+2索引让我觉得最有可能进行越界访问。 I copied your program and added a line: 我复制了你的程序并添加了一行:

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

When I ran the program, it printed OUT OF RANGE . 当我运行该程序时,它打印了OUT OF RANGE

As for the warnings you get from gcc -Wall -pedantic , they're not really a problem. 至于你从gcc -Wall -pedantic获得的警告,它们并不是真正的问题。 The warning about the // comments can be avoided by compiling with -std=c99 . 使用-std=c99进行编译可以避免有关//注释的警告。 The "missing braces" warning is spurious. “缺失的大括号”警告是虚假的。 Nested braces in initializers for nested data structures are optional, and {0} is a perfectly valid idiom for initializing an entire data structure (array, struct, union) to zero. 嵌套数据结构的初始值设定项中的嵌套大括号是可选的, {0}是将整个数据结构(数组,结构,并集)初始化为零的完全有效的惯用法。 Recent versions of gcc (5.2.0 in particular) don't warn about it. 最新版本的gcc(特别是5.2.0)没有对此发出警告。

Recent versions of clang and gcc come with a tool that trivializes such questions. clang和gcc的最新版本附带了一个可以轻视这些问题的工具。 Please always use it, it will save you a lot of time looking for errors. 请始终使用它,它将为您节省大量时间寻找错误。

$ 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
              ^

Apparently, cygwin might not support libubsan yet, so you may need -fsanitize-undefined-trap-on-error which replaces the nice error message with a simple trap, which you can then investigate with gdb. 显然,cygwin可能还不支持libubsan,所以你可能需要-fsanitize-undefined-trap-on-error ,它用一个简单的陷阱取代了很好的错误信息,你可以用gdb进行调查。 Yes, a debugger is another tool and will require a bit of time to learn, but not that much, and it will save you more time looking for bugs. 是的,调试器是另一种工具,需要一点时间来学习,但不是那么多,它将为您节省更多时间来查找错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM