Почему следующий код приводит к отказу Сегментации? (Я пытаюсь создать две матрицы того же размера, один с помехами и другим с динамическим выделением),
#include <stdio.h>
#include <stdlib.h>
//Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
int a[X][Y];
int** b = (int**) malloc(sizeof(int*) * X);
for(i=0; i<X; i++){
b[i] = malloc (sizeof(int) * Y);
}
}
Достаточно странно, если я комментирую одно из матричных определений, код хорошо работает. Как это:
#include <stdio.h>
#include <stdlib.h>
//No Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
//int a[X][Y];
int** b = (int**) malloc(sizeof(int*) * X);
for(i=0; i<X; i++){
b[i] = malloc (sizeof(int) * Y);
}
}
или
#include <stdio.h>
#include <stdlib.h>
//No Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
int a[X][Y];
//int** b = (int**) malloc(sizeof(int*) * X);
//for(i=0; i<X; i++){
// b[i] = malloc (sizeof(int) * Y);
//}
}
Я выполняю gcc на Linux на 32-разрядной машине.
Править: Проверка, успешно выполняется ли malloc ():
#include <stdio.h>
#include <stdlib.h>
//No Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
int a[X][Y];
int* tmp;
int** b = (int**) malloc(sizeof(int*) * X);
if(!b){
printf("Error on first malloc.\n");
}
else{
for(i=0; i<X; i++){
tmp = malloc (sizeof(int) * Y);
if(tmp)
b[i] = tmp;
else{
printf("Error on second malloc, i=%d.\n", i);
return;
}
}
}
}
Ничто не распечатывается, когда я работаю, это (ожидайте, конечно, для "Отказа сегментации"),
Вы получаете ошибку сегментации, что означает, что ваша программа пытается получить доступ к адресу памяти, который не был назначен ее процессу. Массив a
является локальной переменной и, таким образом, выделяет память из стека. Как unwind
указал ,
требует 120 Мбайт памяти. Это почти наверняка больше, чем пространство стека, выделенное ОС для вашего процесса. Как только цикл for выходит за пределы стека, возникает ошибка сегментации.
В Linux размером стека управляет ОС, а не компилятор, поэтому попробуйте следующее: -
$ ulimit -a
В ответе вы должны увидеть примерно такую строку: -
stack size (kbytes) (-s) 10240
Это означает, что каждый процесс получает 10 Мбайт памяти. , далеко не достаточно для вашего большого массива.
Вы можете настроить размер стека с помощью команды ulimit -s
, но я подозреваю, что она не позволит вам выбрать размер стека 120 Мбайт!
Простейшее решение - сделать
глобальной переменной вместо локальной.
Ваш третий код тоже не работает (по крайней мере, в моей системе).
Попробуйте выделить память для массива a
в куче (когда размеры большие).
Попробуйте увеличить лимиты кучи и стека в GCC:
gcc -Wl,--stack=xxxxx -Wl,--heap=yyyyy
Это значительные выделения. Вы пытались проверить, успешно ли выполняется malloc ()?
Вы можете использовать malloc () для всех ваших массивов и каждый раз проверять, будет ли он успешным.
Возможно, компилятор просто меняет указатель стека на какое-то большое значение но никогда не использовал его и, таким образом, никогда не приводил к нарушению доступа к памяти.
Попробуйте инициализировать все элементы A в третьем примере? Ваш первый пример пытается выделить B после A в стеке, и доступ к стеку на таком высоком уровне (при первом назначении B) может быть причиной segfault.
Обе матрицы не умещаются в пределах вашей памяти. Вы можете выделить только по одному.
Если вы определяете Y как 3000 вместо 6000, ваша программа не должна выдавать segfault.
Для вашей переменной a
в 32-битной системе требуется 5000 * 6000 * 4 = 120 МБ стека. Возможно, это нарушает какой-то предел, что вызывает ошибку сегментации.
Кроме того, конечно, возможно, что в какой-то момент произойдет сбой malloc ()
, что может заставить вас разыменовать указатель NULL
.
Переполнение стека (насколько это уместно!) Может привести к ошибке сегментации, которую, похоже, вы здесь видите.
В вашем третьем случае указатель стека перемещается на недопустимый адрес, но не используется ни для чего, поскольку затем программа завершается. Если вы поместите какую-либо операцию после выделения стека, вы должны получить segfault.