Выделение памяти для матрицы в 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-разрядной машине.

Править: Проверка, успешно выполняется ли 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
задан Prasoon Saurav 8 September 2010 в 03:11
поделиться

8 ответов

Вы получаете ошибку сегментации, что означает, что ваша программа пытается получить доступ к адресу памяти, который не был назначен ее процессу. Массив a является локальной переменной и, таким образом, выделяет память из стека. Как unwind указал , требует 120 Мбайт памяти. Это почти наверняка больше, чем пространство стека, выделенное ОС для вашего процесса. Как только цикл for выходит за пределы стека, возникает ошибка сегментации.

В Linux размером стека управляет ОС, а не компилятор, поэтому попробуйте следующее: -

$ ulimit -a

В ответе вы должны увидеть примерно такую ​​строку: -

stack size (kbytes)            (-s)  10240

Это означает, что каждый процесс получает 10 Мбайт памяти. , далеко не достаточно для вашего большого массива.

Вы можете настроить размер стека с помощью команды ulimit -s , но я подозреваю, что она не позволит вам выбрать размер стека 120 Мбайт!

Простейшее решение - сделать глобальной переменной вместо локальной.

2
ответ дан 5 December 2019 в 12:57
поделиться

Ваш третий код тоже не работает (по крайней мере, в моей системе).

Попробуйте выделить память для массива a в куче (когда размеры большие).

0
ответ дан 5 December 2019 в 12:57
поделиться

Попробуйте увеличить лимиты кучи и стека в GCC:

gcc -Wl,--stack=xxxxx -Wl,--heap=yyyyy
2
ответ дан 5 December 2019 в 12:57
поделиться

Это значительные выделения. Вы пытались проверить, успешно ли выполняется malloc ()?

Вы можете использовать malloc () для всех ваших массивов и каждый раз проверять, будет ли он успешным.

1
ответ дан 5 December 2019 в 12:57
поделиться

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

Попробуйте инициализировать все элементы A в третьем примере? Ваш первый пример пытается выделить B после A в стеке, и доступ к стеку на таком высоком уровне (при первом назначении B) может быть причиной segfault.

1
ответ дан 5 December 2019 в 12:57
поделиться

Обе матрицы не умещаются в пределах вашей памяти. Вы можете выделить только по одному.

Если вы определяете Y как 3000 вместо 6000, ваша программа не должна выдавать segfault.

0
ответ дан 5 December 2019 в 12:57
поделиться

Для вашей переменной a в 32-битной системе требуется 5000 * 6000 * 4 = 120 МБ стека. Возможно, это нарушает какой-то предел, что вызывает ошибку сегментации.

Кроме того, конечно, возможно, что в какой-то момент произойдет сбой malloc () , что может заставить вас разыменовать указатель NULL .

6
ответ дан 5 December 2019 в 12:57
поделиться

Переполнение стека (насколько это уместно!) Может привести к ошибке сегментации, которую, похоже, вы здесь видите.

В вашем третьем случае указатель стека перемещается на недопустимый адрес, но не используется ни для чего, поскольку затем программа завершается. Если вы поместите какую-либо операцию после выделения стека, вы должны получить segfault.

1
ответ дан 5 December 2019 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: