Ошибка сегмента при инициализации массива - PullRequest
8 голосов
/ 28 сентября 2010

Я беру урок на C и сталкиваюсь с ошибкой сегментации.Из того, что я понимаю, ошибки сегмента должны возникать, когда вы обращаетесь к памяти, которая не была выделена, или иным образом за пределами.Конечно, все, что я пытаюсь сделать, это инициализировать массив (хотя и довольно большой)

Я просто неправильно понимаю, как анализировать 2d массив?Неправильное наложение границы - это именно то, что может вызвать ошибку сегмента - я ошибаюсь, используя для этого вложенный for-loop?

Профессор предоставил функции часов, так что я надеюсь, что это не проблема.Я запускаю этот код в Cygwin, это может быть проблемой?Исходный код следует.Также используется стандарт c99.

Чтобы быть совершенно ясным: я ищу помощь в понимании (и в конечном итоге исправлении) причины, по которой мой код вызывает ошибку сегмента.

#include <stdio.h>
#include <time.h>
int main(void){
   //first define the array and two doubles to count elapsed seconds.   
   double rowMajor, colMajor;
   rowMajor = colMajor = 0;
   int majorArray [1000][1000] = {};

   clock_t start, end;

   //set it up to perform the test 100 times.
   for(int k = 0; k<10; k++)
   {
   start=clock();
   //first we do row major
   for(int i = 0; i < 1000; i++)
   {
       for(int j = 0; j<1000; j++)
       {
           majorArray[i][j] = 314;
       }
   }
   end=clock();
   rowMajor+= (end-start)/(double)CLOCKS_PER_SEC;
   //at this point, we've only done rowMajor, so elapsed = rowMajor
   start=clock();
   //now we do column major
     for(int i = 0; i < 1000; i++)
   {
       for(int j = 0; j<1000; j++)
       {
           majorArray[j][i] = 314;
       }
   }
   end=clock();
   colMajor += (end-start)/(double)CLOCKS_PER_SEC;
   }
   //now that we've done the calculations 100 times, we can compare the values.
   printf("Row major took %f seconds\n", rowMajor);
   printf("Column major took %f seconds\n", colMajor);
   if(rowMajor<colMajor)
   {
     printf("Row major is faster\n");
   }
   else
   {
      printf("Column major is faster\n");
   }

   return 0;

}

Ответы [ 6 ]

10 голосов
/ 28 сентября 2010

Ваша программа корректно работает на моем компьютере (x86-64 / Linux), поэтому я подозреваю, что вы работаете с системным ограничением размера стека вызовов. Я не знаю, сколько у вас стека на Cygwin, но ваш массив составляет 4 000 000 байт (с 32-битным int) - это может быть слишком большим.

Попробуйте переместить объявление majorArray из main (поместите его сразу после #include s) - тогда это будет глобальная переменная, которая поступает из другого пула распределения, который может быть намного больше.

Кстати, это сравнение обратное:

if(rowMajor>colMajor)
{
  printf("Row major is faster\n");
}
else
{
   printf("Column major is faster\n");
}

Кроме того, чтобы сделать такой тест, вам действительно нужно повторить процесс для множества различных размеров и форм массива.

6 голосов
/ 28 сентября 2010

Вы пытаетесь захватить 1000 * 1000 * sizeof( int ) байт в стеке.Это больше, чем ваша ОС позволяет наращивать стек.Если на любом Unix - проверьте ulimit -a на максимальный размер стека процесса.

Как правило - выделите большие структуры в куче с malloc(3).Или используйте статические массивы - вне области действия любой функции.

В этом случае вы можете заменить объявление majorArray на:

int (*majorArray)[1000] = calloc(1000, sizeof majorArray);
3 голосов
/ 28 сентября 2010

Мне не удалось найти какую-либо ошибку в вашем коде, поэтому я скомпилировал ее, запустил и работал как ожидалось.

Однако в вашем коде есть семантическая ошибка:

   start=clock();
   //set it up to perform the test 100 times.
   for(int k = 0; k<10; k++)
   {

Должно быть:

   //set it up to perform the test 100 times.
   for(int k = 0; k<10; k++)
   {
   start=clock();

Кроме того, условие в конце должно быть изменено на обратное:

if(rowMajor<colMajor)

Наконец, чтобы избежать проблемы стека, специфичного для ОСРазмер других упомянутых, вы должны определить вашу матрицу вне main ():

#include <stdio.h>
#include <time.h>

int majorArray [1000][1000];

int main(void){
   //first define the array and two doubles to count elapsed seconds.   
   double rowMajor, colMajor;
   rowMajor = colMajor = 0;
1 голос
/ 28 сентября 2010

Программа отлично работает при компиляции gcc и работает в Linux, Cygwin вполне может быть вашей проблемой здесь.

1 голос
/ 28 сентября 2010

Этот код отлично работает для меня под Linux, и я не вижу в этом ничего заведомо неправильного. Вы можете попробовать отладить его через GDB. Скомпилируйте это так:

gcc -g -o testcode test.c

и затем произнесите

gdb ./testcode

и в GDB сказать run

В случае сбоя произнесите where, и GDB сообщит вам, где произошел сбой Тогда вы теперь в какой строке ошибка.

0 голосов
/ 28 сентября 2010

Если он работает правильно в другом месте, вы, скорее всего, пытаетесь получить больше места в стеке, чем позволяет ОС.Вы выделяете 4MB в стеке (1 миллион целых чисел), что слишком много для «безопасного» размещения в стеке.malloc () и free () - ваши лучшие ставки здесь.

...