Как правильно обращаться с «нехваткой памяти»? - PullRequest
7 голосов
/ 17 сентября 2009

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

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

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

Ответы [ 7 ]

12 голосов
/ 17 сентября 2009

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

В операционных системах, которые поддерживают сбои, я видел два общих шаблона:

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

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

6 голосов
/ 17 сентября 2009

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

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

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

1 голос
/ 17 сентября 2009

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

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

1 голос
/ 17 сентября 2009

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

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

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

0 голосов
/ 17 сентября 2009

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

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

0 голосов
/ 17 сентября 2009

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

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

0 голосов
/ 17 сентября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...