Есть два разных предела памяти. Ограничение виртуальной памяти и ограничение физической памяти.
Виртуальная память
Виртуальная память ограничена размером и расположением доступного адресного пространства. Обычно в самом начале выполняется исполняемый код и статические данные, а в прошлом - куча, а в конце - область, зарезервированная ядром, перед ним разделяемые библиотеки и стек (который на большинстве платформ уменьшается). Это дает пространство для кучи и стека для роста, остальные области известны при запуске и исправлении.
Свободная виртуальная память изначально не помечается как используемая, но помечается таковой во время выделения. Хотя куча может увеличиваться до всей доступной памяти, большинство систем не наращивают стеки автоматически. Предельное значение по умолчанию для стека IIRC составляет 8 МБ в Linux и 1 МБ в Windows и может быть изменено в обеих системах. Виртуальная память также содержит любые отображенные в памяти файлы и оборудование.
Одна из причин, по которой стек не может быть автоматически увеличен (произвольно), состоит в том, что многопоточным программам требуется отдельный стек для каждого потока, поэтому они в конечном итоге будут мешать друг другу.
На 32-разрядных платформах общий объем виртуальной памяти составляет 4 ГБ, и Linux, и Windows обычно резервируют последний 1 ГБ для ядра, что дает вам максимум 3 ГБ адресного пространства. Существует специальная версия Linux, которая ничего не резервирует, предоставляя вам полный 4GiB. Это полезно в редких случаях больших баз данных, где последний 1 ГБ экономит день, но при регулярном использовании он немного медленнее из-за дополнительных перезагрузок таблицы страниц.
На 64-битных платформах виртуальная память составляет 64EiB, и вам не нужно об этом думать.
Физическая память
Физическая память обычно выделяется операционной системой только тогда, когда процессу требуется доступ к ней. Сколько физической памяти использует процесс, очень нечеткое число, поскольку некоторая память распределяется между процессами (код, общие библиотеки и любые другие сопоставленные файлы), данные из файлов загружаются в память по требованию и удаляются при нехватке памяти и «анонимная» память (та, которая не поддерживается файлами) может быть заменена.
В Linux то, что происходит, когда у вас заканчивается физическая память, зависит от vm.overcommit_memory
настроек системы. По умолчанию это overcommit. Когда вы просите систему выделить память, она отдает вам часть, а выделяет только виртуальную память. Когда вы на самом деле обращаетесь к памяти, она попытается использовать физическую память, отбрасывая данные, которые можно перечитать, или заменяя их по мере необходимости. Если он обнаружит, что не может ничего освободить, он просто удалит процесс из существования (нет способа реагировать, потому что для этой реакции может потребоваться больше памяти, и это приведет к бесконечному циклу).
Вот как процессы умирают на Android (который также является Linux). Логика была улучшена с логикой, который процесс, чтобы удалить из существования на основе того, что процесс делает и сколько ему лет. Процессы Android просто перестают делать что-либо, но сидят на заднем плане, и «убийца нехватки памяти» убьет их, когда ему понадобится память для новых.