Почему malloc() или new никогда не возвращают NULL?

Я пишу приложение, которое требует большой памяти для кеширования, поскольку я описал его здесь. Теперь я играю с некоторыми malloc/новыми конструкциями, чтобы понять, как я мог это реализовать. Я сделал странное замечание:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  while(1) {
    char *foo = (char*)malloc(1024);// new char[1024];
    if(foo == NULL) { 
      printf("Couldn't alloc\n");
      fflush(stdout);
      return 0;
    }
  }
  return 0;
}

Почему этот printf никогда не был достигнут? Если в моей системе не хватает памяти, malloc, как говорят, возвращает NULL, как объясняется здесь. Но я всегда получаю SIGKILL (я использую linux...).

Ответы

Ответ 1

Linux по умолчанию обычно использует оппортунистическую схему распределения памяти, то есть ядро ​​даст вам действительный адрес, который не будет выделен до первого использования.

См:

В соответствии с этими ответами вы можете отключить эту функцию, используя echo 2 > /proc/sys/vm/overcommit_memory.

Из того, что я могу сказать, это делается в предположении, что вы не обязательно будете использовать всю память, которую вы выделите. Я не могу сказать, что я лично когда-либо выделял пространство, которое я не касаюсь хотя бы один раз, поэтому мне было бы интересно узнать, как это влияет на реальную жизнь...

Что касается сбоя SIGKILL, каждый вызов malloc по-прежнему распределяет некоторую память для каждого вызова. В конце концов, вы, скорее всего, наполните память памятью malloc и, таким образом, вызовете ярость функции отключения памяти. Независимо от того, является ли это проблемой или если, возможно, политика overcommit по-прежнему выделяет часть требуемого пространства, это хороший вопрос.

Ответ 2

Обычно Linux выделяет столько же (виртуальной) памяти, сколько вы запрашиваете, и только выделяет для нее физическую память, когда это необходимо. Если в системе заканчивается физическая память, тогда она начинает уничтожать процессы, чтобы освободить их.

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

Подробнее см. справочную страницу malloc и ее ссылки:

По умолчанию Linux следует оптимистичной стратегии распределения памяти.        Это означает, что когда malloc() возвращает non NULL, нет гарантии        что память действительно доступна. В случае, если окажется, что        система потеряла память, один или несколько процессов будут убиты        Убийца OOM. Для получения дополнительной информации см. Описание        /proc/sys/vm/overcommit _memory и /proc/sys/vm/oom _adj в proc(5), и        исходный файл ядра Documentation/vm/overcommit-accounting.

(И, конечно, new не будет возвращать нуль в любом случае, если вы не используете версию без броска).

Ответ 3

malloc возвращает NULL, если запрошенное распределение не может быть выполнено. Но, возможно, вам стоит попробовать выделить тонны пространства из кучи.

Смотрите здесь.

В linux единственный способ получить ошибку при вызове malloc() - это отключить переопределение памяти. В обычных системах linux это единственный способ для malloc() вернуть NULL. Если процесс icecast достигнет этот момент, он ввернул все равно, он ничего не сможет сделать значимый: любые исходные сообщения будут сбой (refbuf alloc), любой журнал печати (printf также использует malloc), поэтому он может также отказаться от call abort().

Ответ 4

Malloc вернет NULL, если операционная система позволит вашей программе работать так долго. Но прежде чем malloc получит шанс запустить операционную систему, ваш компьютер будет убивать.

Так же, как он убивает ваш процесс, если он обнаружил, что вы пишете внешние страницы памяти, выделенные для вашего процесса.