Должны ли мы проверить, если распределение памяти не удается? - PullRequest
13 голосов
/ 29 октября 2011

Я видел много кода, который проверяет наличие указателей NULL при каждом выделении.Это делает код многословным, и, если это не делается последовательно, только тогда, когда программист почувствует, что это так, даже не гарантирует, что программа не будет аварийно завершена, когда закончится адресное пространство.Кроме того, если программа не может выделять больше ресурсов, она все равно не сможет выполнять свою функцию, верно?

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

Примечание

Я говорю о настольных приложениях, которые работают на современных компьютерах (адресное пространство не менее 2 ГБ),и что наиболее определенно не работают космические челноки, системы жизнеобеспечения или нефтяные платформы BP.Самое главное, я говорю о программах, которые используют malloc, но никогда не превышают 5 МБ памяти.

Ответы [ 7 ]

11 голосов
/ 30 октября 2011

Всегда проверяйте возвращаемое значение, но для ясности обычно оборачивать malloc() в функцию, которая никогда не возвращает NULL:

void *
emalloc(size_t amt){
    void *v = malloc(amt);  
    if(!v){
        fprintf(stderr, "out of mem\n");
        exit(EXIT_FAILURE);
    }
    return v;
}

Затем, позже вы можете использовать

char *foo = emalloc(56);
foo[12] = 'A';

Без совести.

8 голосов
/ 29 октября 2011

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

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

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

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

7 голосов
/ 05 февраля 2013

Аналогично подходу Дэйва выше, но добавляет макрос, который автоматически проходит имя файла и номер строки в нашей программе распределения, чтобы мы могли сообщить эта информация в случае сбоя.

#include <stdio.h>
#include <stdlib.h>

#define ZMALLOC(theSize) zmalloc(__FILE__, __LINE__, theSize)

static void *zmalloc(const char *file, int line, int size)
{
   void *ptr = malloc(size);

   if(!ptr)
   {
      printf("Could not allocate: %d bytes (%s:%d)\n", size, file, line);
      exit(1);
   }

   return(ptr);
}

int main()
{
   /* -- Set 'forceFailure' to a non-zero value in order to observe
         how 'zmalloc' behaves when it cannot allocate the
         requested memory -- */

   int bytes        = 10 * sizeof(int);
   int forceFailure = 0;
   int *anArray     = NULL;

   if(forceFailure)
      bytes = -1;

   anArray = ZMALLOC(bytes);

   free(anArray);

   return(0);
}
2 голосов
/ 29 октября 2011

, но гораздо труднее устранить неполадки, если вы не регистрируете, где произошел сбой malloc.

не удалось выделить память в строке XX - предпочтительнее, чем просто вылет.

1 голос
/ 29 октября 2011

В размещенной среде ошибка проверки возврата malloc в настоящее время не имеет особого смысла. Большинство машин имеют виртуальное адресное пространство 64 бит. Вам понадобится много времени, чтобы исчерпать это. Ваша программа, скорее всего, потерпит неудачу в совершенно другом месте, а именно, когда ваша физическая + подкачка памяти исчерпана. До этого он показал совершенно нелепую производительность, потому что он только менялся, и пользователь сработал бы Cntrl-C задолго до того, как вы туда пришли.

Сегфагтинг "красиво" на нулевой ссылке на указатель будет четкой точкой, чтобы увидеть, где что-то происходит в отладчике Но в своей практике я никогда не видел неудавшуюся malloc причину.

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

Редактировать: Чтобы уточнить это после редактирования вопроса. Описанные там программы / системы явно не «встроены». Я никогда не видел, чтобы malloc терпел неудачу при описанных там обстоятельствах.

1 голос
/ 29 октября 2011

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

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

0 голосов
/ 06 декабря 2012

Я хотел бы добавить, что крайние случаи всегда должны проверяться, даже если вы считаете, что они безопасны или не могут привести к другим проблемам, кроме сбоя. Разыменование нулевого указателя потенциально может быть использовано (http://uninformed.org/?v=4&a=5&t=sumry).

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