Malloc не работает после некоторых вызовов (C, скомпилирован с gcc для MinGW-W64 в Windows 10) - PullRequest
1 голос
/ 06 июня 2019

Мне нужно проверить производительность моего проекта в Windows.
У меня есть массив массивов rede_conexoes, и я выделяю каждую позицию в цикле, но после некоторых итераций функция malloc не работает ивнезапно останавливает мой процесс, прежде чем я могу даже проверить возвращаемое значение и не показывает сообщение об ошибке.

Код прекрасно работает на WSL (Windows Subsystem for Linux) в Windows 10. Для собственного тестирования кода в WindowsЯ установил Mingw-w64 для компилятора gcc (не смог найти лучшего решения, так как необходима поддержка OpenMP).
Вот фрагмент кода с функцией malloc:

bool **rede_conexoes = (bool**) malloc(num_PL * sizeof(bool*));
...
for(int i = 0; i < num_PL; i++){
    rede_conexoes[i] = (bool*)malloc(num_PL*sizeof(bool)); // <- Error occurs here
    if(rede_conexoes[i] == NULL) exit(1); // <- Can't get to this line after the error
    for(int j = 0; j < num_PL; j++)
        fscanf(model, "%d", (int*)&rede_conexoes[i][j]);
}

Я не понимаю, как это может работать без проблем на WSL, но в Windows происходит сбой, и нет сообщения об ошибке.
Я заметил, что он начинает работать, когда num_PL больше 2^3 = 8, проблем нетесли num_PL больше, чем 2^15 = 32768 в Linux.Я протестировал .exe, созданный gcc в командной строке (cmd) и PowerShell, оба с одинаковыми результатами.

Ответы [ 2 ]

3 голосов
/ 06 июня 2019

Когда вы читаете последнее число (когда i == num_PL - 1 и j == num_PL - 1) в &rede_conexoes[i][j], вы выделили пространство для bool (обычно 1 байт), но попросили время выполнения прочитать в int (обычно 4 или иногда 8 байтов). Это потенциально записывает несколько байтов после конца выделенного пространства. Это приводит к неопределенному поведению, приводящему к тому, что программа работает, работает неправильно или дает сбой.

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

Одним из решений, как упомянуто в комментариях, было бы прочитать целое число в локальную переменную типа int, а затем присвоить его вашему массиву bool.

0 голосов
/ 06 июня 2019

Возможно, операционному процессору не разрешено выделять вам всю эту память.

Предполагается, что вы работаете с квадратичным двумерным (2D) массивом:

2^15 * 2^15 = 32.768 * 32.768 = 1.073.741.824 booleans!

Если вы используете этот код в 32-битной архитектуре sizeof(bool*) = 4:

1.073.741.824 * 4 = 4.294.967.296 (4GB)

Если вы используете этот код в 64-битной архитектуре sizeof(bool*) = 8:

1.073.741.824 * 8 = 8.589.934.592 (8GB)

Вся эта память доступна для процесса вызова?

...