C: предел строки? Нет ошибки/предупреждения компилятора - почему?

Я кодирую некоторые вещи mqtt. Максимальный размер допустимого сообщения mqtt — 268435455 байт примерно 260 МБ.

Теперь я столкнулся с несколькими ошибками сегментации в своем коде, и выяснилось, что я не могу использовать *char такого размера в C (Rasbian/Debian 9: Linux zentrale 5.10.103-v7+ #1529 SMP Tue Mar 8 12:21:37 GMT 2022 armv7l GNU/Linux).

В целях тестирования я написал следующий пример программы:

#include <stdio.h> 
#include <string.h>
#define MAX_STRING 268435456 

int main()
{
int i;

void function()
{
        char    message[MAX_STRING];

        printf("0\n");
        memset(message,0,sizeof(message));
        printf("1\n");
        return;
}

i=1;
printf("i: %d\n",i);
i++;
printf("i: %d\n",i);
function();
printf("i: %d\n",i);
}

Я могу скомпилировать его без каких-либо предупреждений или ошибок. При запуске я получаю следующий вывод:

root@rasbpi:/src# ./Beispiel 
i: 1
i: 2
Segmentation fault

(оригинал на немецком языке: Speicherzugriffsfehler)

Я не понимаю, почему я получаю segfault. Если размер слишком велик, разве компилятор не должен жаловаться? Если ограничений нет и системе не хватает памяти (а это не так!) я должен получить ошибку OOM, но не segfault.

Кто-нибудь может мне это объяснить?

Спасибо

/КНЭББ

🤔 А знаете ли вы, что...
C используется для создания библиотек и фреймворков, которые расширяют его функциональность.


44
1

Ответ:

Решено

Вы выделяете место для массива символов в стеке.

Компиляторы обычно не знают, сколько памяти выделено для стека. Это было бы бессмысленно, поскольку они не знают, сколько стека могут использовать другие модули конечной программы. И если рекурсия вступает в игру, используемое пространство стека может быть неопределимым.

Линкер тоже не может этого сделать.

ABI цели определяет размер стека.

Обычные цели имеют стеки размером от нескольких десятков байт (микроконтроллер) до нескольких мегабайт (ПК).

Таким образом, вы достигаете предела не языка, а своей цели.

Решите свою проблему, выделив необходимое место с помощью malloc().