Linux гарантирует освобождение памяти malloc'd при выходе из программы?

Раньше я считал, что это так, но... Я не могу найти это прямо заявленным.

man 3 exit и man 2 _exit подробно определяют эффекты завершения процесса, но не упоминают утечки памяти.

Posix подходит ближе: он упоминает это:

  • Отображения памяти, которые были созданы в процессе, должны быть удалены, прежде чем процесс будет уничтожен.

  • [TYM] [Option Start] Любые блоки типизированной памяти, которые были отображены в вызывающем процессе, должны быть не отображены, как если munmap() неявно вызывался munmap() для их отображения. [Вариант Конец]

Смешивая это с man 3 malloc:

Обычно malloc() выделяет память из кучи и корректирует размер кучи по мере необходимости, используя sbrk(2). При выделении блоков памяти, превышающих байты MMAP_THRESHOLD, реализация glibc malloc() выделяет память как частное анонимное отображение, используя mmap(2).

Таким образом, мы можем заключить, что если malloc вызвал mmap то завершение процесса может сделать соответствующий вызов munmap, НО... (a) теги "необязательной функции" в этой спецификации POSIX вызывают беспокойство, (b) это mmap но что о sbrk? (c) Linux не на 100% совместим с POSIX, поэтому я не уверен, требуется ли смешивание документов Linux со спецификациями Posix

Причина, по которой я спрашиваю, состоит в том, что... Когда сбой вызова библиотеки, мне разрешено просто выйти?

if(somecall() == -1) {
    error(EXIT_FAILURE, errno, "Big fat nasty error.\n");
}

Или мне нужно идти вверх по стеку, чтобы убедиться, что все вплоть до main() free() и будет вызывать только exit или error в main()?

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

Ответ 1

Это "освобождение" выполняется на уровне ядра. Таким образом, вы вряд ли найдете что-то прямое в спецификациях POSIX API или C, поскольку виртуальная память намного "ниже" их. Так что вы вряд ли найдете что-либо актуальное - не говоря уже о гарантиях.

В Linux ядро освобождает память при выходе из процесса (как sbrk, так и mmap), что гарантировано. Смотрите исходный код мм.

Могу ли я просто выйти из системы при сбое вызова библиотеки?

Да. Это нормально делать.

Однако обратите внимание, что могут возникнуть и другие соображения, такие как неочищенные временные файлы, открытые подключения к базе данных/сети и т.д. Например, если ваша программа оставляет соединение с базой данных открытым и выходит, серверная сторона может не знать, когда закрывать соединение.

Вы можете прочитать больше о Virtual Memory Manager (он основан на более старом ядре, но идея все еще применима).

Ответ 2

Я уверен, что комитет POSIX предполагал, что вся память, выделенная malloc должна быть освобождена как одно из "последствий завершения процесса", перечисленных в спецификации _exit которой вы связаны. Я также могу сказать вам, что на практике каждая реализация Unix, которую я когда-либо использовал, делала это.

Тем не менее, я думаю, что вы нашли подлинный пробел в спецификациях. POSIX ничего не говорит о памяти, выделенной sbrk, потому что вообще не указывает sbrk. Его спецификация для malloc более или менее взята дословно из стандарта C, и стандарт C намеренно не говорит, что вся память, выделенная malloc должна быть освобождена после "нормального завершения", потому что существуют встроенные среды, которые не делают тот. И, как вы указали, "отображения памяти, которые были созданы в процессе", можно прочитать, чтобы применить их только к выделениям, сделанным непосредственно с помощью mmap, shmat и тому подобного. Возможно, стоит подать запрос на устный перевод в Austin Group.