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

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

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

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

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

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

Действительно ли мое обоснование (достаточно) нормально?

Обновленный:

  1. Функция "safe_malloc" может быть полезной при отладке и могла бы быть полезной иначе
  2. +X доступ может скрыть первопричину Нулевого указателя
  3. На Linux, "оптимистическое выделение памяти" может тень, вырисовывающаяся OOM условия (Из памяти)
22
задан jldupont 22 December 2009 в 15:15
поделиться

10 ответов

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

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

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

19
ответ дан 29 November 2019 в 04:12
поделиться

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

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

11
ответ дан 29 November 2019 в 04:12
поделиться

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

2
ответ дан 29 November 2019 в 04:12
поделиться

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

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

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

7
ответ дан 29 November 2019 в 04:12
поделиться

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

0
ответ дан 29 November 2019 в 04:12
поделиться

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

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

2
ответ дан 29 November 2019 в 04:12
поделиться

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

assert(ptr != NULL);

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

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

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

2
ответ дан 29 November 2019 в 04:12
поделиться

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

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

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

1
ответ дан 29 November 2019 в 04:12
поделиться

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

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

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

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

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

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

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

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

0
ответ дан 29 November 2019 в 04:12
поделиться

Ассигнования могут не состояться по нескольким причинам. То, что вы делаете (и можете сделать) с этим, зависит отчасти от сбоя аллокаций.

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

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

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

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

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

.
7
ответ дан 29 November 2019 в 04:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: