Linux оптимистичный malloc:будет ли new всегда выбрасываться при нехватке памяти?

StackOverflow https://stackoverflow.com/questions/1655650

Вопрос

Я читал об условиях нехватки памяти в Linux, и следующий абзац со страниц руководства заставил меня задуматься:

По умолчанию Linux придерживается оптимистичной стратегии распределения памяти.Это означает, что когда malloc() возвращает значение, отличное от NULL, нет никакой гарантии, что память действительно доступна.Это действительно серьезная ошибка.В случае, если окажется, что в системе не хватает памяти, один или несколько процессов будут уничтожены печально известным ООМ-убийцей.[...]

Учитывая, что реализация operator new в какой-то момент завершится вызовом malloc, есть ли какие-либо гарантии, что new действительно будет запущен в Linux?Если их нет, то как справиться с этой, по-видимому, необнаруживаемой ситуацией с ошибкой?

Это было полезно?

Решение

Это зависит; Вы можете настроить настройки Overcommit в ядре Использование vmovercommit_memory.

Херб Саттер обсудил несколько лет назад, как Такое поведение на самом деле не соответствует стандарту C ++:

«В некоторых операционных системах, в том числе в частности Linux, распределение памяти всегда преуспевает. Полная остановка. Как распределение может всегда добиваться успеха, даже если запрашиваемая память действительно недоступна? Причина в том, что само распределение просто записывает запрос на память; В соответствии с обложками (физическая или виртуальная) память фактически не привержена запрашивающему процессу с реальным хранилищем поддержки, пока память фактически не будет использована.

«Обратите внимание, что если New использует средства операционной системы напрямую, то новый всегда будет успешным, но любой более поздний невинный код, такой как BUF [100] = 'c'; может бросить или остановить или остановить. С стандартной точки зрения C ++, оба эффекта не совпадают, поскольку стандарт C ++ требует, чтобы, если новое не могло сделать достаточную память, она не должна сбой (это не), и этот код, как BUF [100] = 'C' мощь)."

Другие советы

Вы не можете справиться с этим в своем программном обеспечении, в чистом виде.

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

Но, как вы видите, все это происходит внутри ядра, ваше приложение этого не видит.Если это критически важная система, вы можете отключить функцию overcommit alltogether в системе.

Я думаю, что Malloc все еще может вернуть NULL. Причина в том, что существует разница между доступной системной памятью (RAM + SWAP) и суммой в адресном пространстве вашего процесса.

Например, если вы попросите 3 ГБ памяти от Malloc на стандартном x86 Linux, он, несомненно, вернет нуль, поскольку это невозможно, учитывая объем памяти, предоставленного приложениям пользовательского пространства.

Простите меня, если я ошибаюсь, но не пытаюсь обнулить выделенную память, чтобы гарантировать, что у вас есть каждый байт, который вы просили? Или даже просто писать на последний байт, это сделало бы исключение, если бы память не была вашей, верна?

Если это правда, вы могли бы просто попытаться написать в последний (и первый?) Байт памяти и посмотреть, работает ли он нормально, и если это не так, вы могли бы вернуть NULL из Malloc.

Да, есть одна гарантия, что новый в конечном итоге бросится. Независимо от Overcommit, объем адресного пространства ограничено. Так что, если вы продолжаете распределять память, рано или поздно у вас будет исчерпываеме место, и новое будет вынуждено бросить.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top