Подтвердить что ты не робот

Всегда проверяйте память malloc'ed?

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

some_small_struct *ptr=(some_small_struct *) malloc(sizeof(some_small_struct));
ptr->some_member= ...;

В словах я выделяю динамическую память для небольшой структуры, и я использую ее напрямую, не проверяя указатель malloc'ed. Я понимаю, что всегда есть вероятность, что программа не получит память, о которой она просит (duh!), Но подумайте о следующем:

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

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

Является ли мой разум здравым (достаточно)?

Обновление

  • Функция "safe_malloc" может быть полезна при отладке и может быть полезной в противном случае
  • +X доступ может скрыть основную причину указателя NULL
  • В Linux "оптимистичное распределение памяти" может скрывать условия OOM (Out-Of-Memory) loomin.
4b9b3361

Ответ 1

Зависит от платформы. Например, в Linux (по умолчанию) нет смысла проверять NULL:

http://linux.die.net/man/3/malloc

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

Ответ 2

В случае C это зависит от платформы. Если вы находитесь на встроенной платформе с очень маленькой памятью, вы должны следить за ней, то, что вы делаете, если это не удается, сложнее сказать. На современной 32-битной ОС с виртуальной памятью система, вероятно, перестанет реагировать и потерпит крах, прежде чем она допустит нехватку памяти. В этом случае, вызов таНос никогда не возвращается, поэтому утилита проверки его значение становится спорным.

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

Ответ 3

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

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

Это, конечно, проблема C и автоматически помещается на С++ с помощью исключений и RAII.
Поскольку новый не вернет NULL, нет смысла проверять.

Ответ 4

Выделение может завершиться по нескольким причинам. То, что вы делаете (и можете делать) об этом, частично зависит от отказа распределения.

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

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

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

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

Наконец, вам нужно подумать о тестировании. Ошибки распределения редки, поэтому вероятность того, что код восстановления был применен в вашем тестировании, исчезает незначительно - если вы не предприняли шаги для обеспечения охвата тестированием, искусственно вызывая сбои. Если вы не собираетесь тестировать код восстановления, то, вероятно, его не стоит писать.

Ответ 5

по крайней мере, я бы поставил assert(ptr != NULL) там, чтобы вы получили значимую ошибку.

Ответ 6

Кроме того, что, если обращение с нулевым указателем еще более усугубляет неустойчивую ситуацию?

Я не понимаю, почему это может усугубить ситуацию.
Во всяком случае, при написании кода для windows ptr- > some_member произойдет нарушение доступа, поэтому вы сразу увидите проблему, поэтому я не вижу причин проверять возвращаемое значение, если у вашей программы нет возможности освободить память. Для платформ, которые не обрабатывают нулевые указатели в хорошем смысле (исключение бросания), опасно игнорировать такие точки.

Ответ 7

Предполагая, что вы работаете в Linux/MaxOs/Windows или другой системе виртуальной памяти, тогда... единственная причина для проверки возвращаемого значения из malloc - это если у вас есть стратегия для освобождения достаточного количества памяти, чтобы позволить программе для продолжения работы. Информационное сообщение поможет в диагностике проблемы, но только в том случае, если ваша программа вызвала проблему нехватки памяти. Обычно это не ваша программа, и единственное, что может сделать ваша программа, это выйти как можно быстрее.

assert(ptr != NULL);

сделает все это. Моя обычная стратегия - иметь слой вокруг malloc, который имеет это в нем.

void *my_malloc(size_t size)
{
    void *ptr = malloc ( size );
    assert(ptr != NULL);
    return *ptr;
}

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

Ответ 8

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

Насколько вы уверены в каждой программе, каждый раз, когда вы делаете редактирование.

Поймайте свои ошибки, чтобы вы могли узнать, что вы врезались вовремя.

Ответ 9

При запуске можно выделить довольно большой кусок памяти, который вы можете освободить, когда вы нажмете состояние из памяти, и используйте это для изящества.

Ответ 10

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

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

Кроме того, в linux память, выделенная для процесса, ограничена. Попробуйте создать 1000 потоков в процессе и выделить некоторую память в каждом из них, тогда вы можете легко имитировать состояние низкой памяти.:)

Всегда лучше проверить значения возврата вызова sys!