Выделение памяти для матрицы в C
Почему следующий код приводит к ошибке сегментации? (Я пытаюсь создать две матрицы одинакового размера, одну со статическим, а другую с динамическим распределением)
#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-разрядной машине.
Edit: проверка, если 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;
}
}
}
}
ничего не распечатывается, когда я его запускаю (ожидайте, конечно, "ошибки сегментации")
8 ответов
вы получаете ошибку сегментации, который означает, что ваша программа пытается получить доступ к адресу памяти, который не был назначен на его процесс. Массив a
локальная переменная и таким образом выделить память из стека. As unwind
указал a
требуется 120 Мбайт памяти. Это почти наверняка больше, чем пространство стека, которое ОС выделила для вашего процесса. Как только цикл for выйдет из конца стека, вы получите сегментацию ошибка.
в Linux размер стека контролируется ОС, а не компилятором, поэтому попробуйте следующее: -
$ ulimit -a
в ответ вы должны увидеть строку примерно так:-
stack size (kbytes) (-s) 10240
это означает, что каждый процесс получает 10 Мбайт памяти, недостаточно близко для вашего большого массива.
вы можете настроить размер стека с помощью ulimit -s <stack size>
команда, но я подозреваю, что она не позволит вам выбрать размер стека 120Mbyte!
самый простой решение-сделать a
глобальная переменная вместо локальной переменной.
код a
переменная требует, на 32-разрядной системе, 5000 * 6000 * 4 = 120 МБ пространства стека. Возможно, это нарушает какой-то предел, что вызывает ошибку сегментации.
кроме того, это, конечно, возможно, что malloc()
в какой-то момент не удается, что может привести к разыменованию a NULL
указатель.
Это значительные ассигнования. Вы пытались проверить, чтобы убедиться, что malloc() преуспевает?
вы можете использовать malloc() для всех массивов, и убедитесь, что это удается каждый раз.
переполнение стека (как уместно!) может привести к сбою сегментации, который, как кажется, вы видите здесь.
в третьем случае указатель стека перемещается на неверный адрес, но не используется ни для чего после программа завершает свою работу. Если вы поместите любую операцию после распределения стека, вы должны получить segfault.
возможно, компилятор просто меняет указатель стека на какое-то большое значение, но никогда не использует его и, таким образом, никогда не вызывает нарушения доступа к памяти.
попробуйте инициализировать все элементы A в вашем третьем примере? Ваш первый пример пытается выделить B после A в стеке, и доступ к стеку, который высок (при первом назначении B), может быть причиной segfault.
Ваш 3-й код тоже не работает (по крайней мере, в моей системе).
попробуйте выделить память для массива a
на куче скорее (когда размеры большие).
обе матрицы не вписываются в пределы вашей памяти. Вы можете выделить только один за раз.
Если вы определяете Y как 3000 вместо 6000, ваша программа не должна выдавать segfault.