Как правильно справиться с «нехваткой памяти»?

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

  •  10-07-2019
  •  | 
  •  

Вопрос

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

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

Мои коллеги, которые пишут серверные программы на Linux, выделяют достаточно памяти для 100 клиентских подключений.Таким образом, хотя его программа может отклонить клиент 101, она никогда не столкнется с ошибкой malloc.Подходит ли его подход и для настольных приложений?

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

Решение

В Linux, malloc() никогда не потерпит неудачу — вместо этого сработает убийца OOM и начнет убивать случайные процессы, пока система не упадет.Поскольку Linux является самой популярной производной UNIX, используемой сегодня, многие разработчики научились никогда не проверять результат malloc().Наверное, поэтому ваши коллеги игнорируют malloc() неудачи.

В ОС, поддерживающих сбои, я видел две общие закономерности:

  • Напишите пользовательскую процедуру, которая проверяет результат malloc(), и звонит abort() если распределение не удалось.Например, GLib и GTK+ библиотеки используют этот подход.

  • Храните глобальный список «очищаемых» выделений, таких как кеши, которые можно очистить в случае сбоя выделения.Затем повторите попытку выделения и, если все равно не удастся, сообщите об этом с помощью стандартных механизмов отчетов об ошибках (которые не выполняют динамическое выделение).

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

Следуйте стандартизированному API

Даже в Linux ulimit можно использовать для быстрого возврата ошибки malloc. Просто по умолчанию он неограничен.

Существует определенное давление, чтобы соответствовать опубликованным стандартам. В большинстве систем, в конечном счете, и в конечном итоге даже в Linux, malloc (3) вернет правильное указание на ошибку. Это правда, что настольные системы имеют виртуальную память и требуют подкачки страниц, но даже тогда не проверяют malloc ( 3) работает только в отлаженной программе без утечек памяти. Если что-то пойдет не так, кто-то захочет установить ulimit и выследить это. Внезапно проверка malloc имеет смысл.

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

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

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

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

Но во многих случаях единственный разумный способ отреагировать на сбой в работе malloc — это завершить программу.Этого можно добиться, если вы позволите вашему коду просто аварийно завершить работу при неизбежном разыменовании нуля.Конечно, всегда было бы лучше выгрузить запись журнала или сообщение об ошибке, объясняющее ошибку, но в реальном мире мы работаем по ограниченному графику.Иногда инвестиции в педантическую обработку ошибок не окупаются.

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

Зависит от приложения, которое вы пишете. Конечно, вам всегда нужно проверять возвращаемое значение malloc (). Тем не менее, обработка OOM грациозно имеет смысл только в тех случаях, например, на важных системных сервисах низкого уровня или при написании библиотеки, которая может быть использована именно ими. Следовательно, наличие оболочки malloc, которая прерывается в OOM, очень часто встречается во многих приложениях и средах. Часто эти оболочки называются xmalloc () или похожими.

GLib g_malloc () также прерывается.

Если вы собираетесь обрабатывать огромные объемы памяти и хотите делать заявления для Linux, например " теперь у меня есть область памяти ABC, и мне не нужна часть B, сделайте, как вы хотите " ;, посмотрите на Семейство функций mmap () / madvise (), доступное в стандартной библиотеке GNU C. В зависимости от ваших шаблонов использования, код может оказаться еще проще, чем с помощью malloc. Этот API также можно использовать, чтобы помочь Linux не тратить память, кэшируя файлы, которые вы собираетесь читать / записывать только один раз.

Они хорошо документированы в информационной документации GNU libc.

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