2015-11-01 2 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; 
} 

Я попытался вставить 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};' to '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} - это совершенно допустимая идиома для инициализации всей структуры данных (array, struct, union) до нуля. Недавние версии 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. Да, отладчик - еще один инструмент, и вам потребуется немного времени, чтобы узнать, но не так много, и это сэкономит вам больше времени на поиск ошибок.