Ошибка сегмента при инициализации массива
Я беру урок на 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 ответов
Ваша программа корректно работает на моем компьютере (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");
}
Кроме того, чтобы сделать такой тест, вам действительно нужно повторить процесс для множества различных размеров и форм массива.
Вы пытаетесь схватить 1000 * 1000 * sizeof( int )
байты в стеке. Это больше, чем ваша ОС позволяет наращивать стек. Если на любом Unix - проверьте ulimit -a
для максимального размера стека процесса.
Как правило - выделяйте большие структуры в куче с помощью malloc(3)
, Или используйте статические массивы - вне области действия любой функции.
В этом случае вы можете заменить декларацию majorArray
с:
int (*majorArray)[1000] = calloc(1000, sizeof majorArray);
Мне не удалось найти ошибку в вашем коде, поэтому я скомпилировал ее, запустил и работал как положено.
Однако в вашем коде есть семантическая ошибка:
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)
Наконец, чтобы избежать проблемы размера стека, специфичной для os, о которой упоминали другие, вы должны определить свою матрицу вне 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;
Этот код отлично работает для меня под Linux, и я не вижу в этом ничего заведомо неправильного. Вы можете попробовать отладить его через GDB. Скомпилируйте это так:
gcc -g -o testcode test.c
а потом сказать
gdb ./testcode
и в GDB говорят run
Если он падает, скажем where
и GDB говорит вам, где произошел сбой. Тогда вы теперь в какой строке ошибка.
Программа отлично работает при компиляции gcc и работает в Linux, Cygwin вполне может быть вашей проблемой здесь.
Если он работает правильно в другом месте, вы, скорее всего, пытаетесь получить больше места в стеке, чем позволяет ОС. Вы выделяете 4MB в стеке (1 миллион целых чисел), что слишком много для "безопасного" размещения в стеке. malloc() и free() - ваши лучшие ставки здесь.