2014-11-09 3 views
2

Следует ли проверять после каждого malloc(), если он был успешным? Возможно ли, что malloc() терпит неудачу? Что происходит тогда?Должен ли я проверить, успешно ли malloc()?

В школе нам сказали, что мы должны проверить, т.е. .:

arr = (int) malloc(sizeof(int)*x*y); 
if(arr==NULL){ 
    printf("Error. Allocation was unsuccessful. \n"); 
    return 1; 
} 

Какова практика в отношении этого? Могу ли я сделать это таким образом:

if(!(arr = (int) malloc(sizeof(int)*x*y)) 
    <error> 
+1

Теоретически, да. В действительности, если malloc не работает, операционная система, вероятно, вот-вот рухнет. PS: Ваш второй пример гораздо труднее прочитать, чем первый, и он должен быть отклонен просмотром кода. –

+1

'arr = (int) malloc (...)' неверно, 'malloc' возвращает указатель. Кроме того: да, вы должны проверить, не сработает ли он, потому что он может выйти из строя. [Также, литье его возвращаемого значения вредно.] (Https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858) –

+0

1. Вам не требуется бросать. 2. Да проверить - почему бы и нет –

ответ

3

Нет необходимости бросить malloc(). Да, необходимо проверить, был ли malloc() успешным или нет. Скажем, malloc() не удалось, и вы пытаетесь получить доступ к выделенной памяти указателя. Это приведет к сбою. Так что лучше поймать выделение памяти, прежде чем получить доступ к указателю.

int *arr = malloc(sizeof(int)); 
if(arr == NULL) 
{ 
printf("Memory allocation failed"); 
return; 
} 
+1

На педантичной ноте этот ответ помогает «проверить, был ли malloc() успешным или нет» - это хорошая идея. Но затем он показывает, как проверить результат 'malloc (sizeof (int))', а не OP 'malloc (sizeof (int) * x * y)'. Тестирование против 'NULL' достаточно для этого' sizeof (int) ', но неверно для OP' sizeof (int) * x * y'. Если 'x * y' -> 0, возврат' NULL' является совместимым кодом и не указывает на выделение памяти. Лучше использовать 'if (arr == NULL && x! = 0 && y! = 0)'. – chux

8

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

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

static inline void *MallocOrDie(size_t MemSize) 
{ 
    void *AllocMem = malloc(MemSize); 
    /* Some implementations return null on a 0 length alloc, 
    * we may as well allow this as it increases compatibility 
    * with very few side effects */ 
    if(!AllocMem && MemSize) 
    { 
     printf("Could not allocate memory!"); 
     exit(-1); 
    } 
    return AllocMem; 
} 

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

Для более общего решения для функций, которые могут не я также, как правило, для реализации простой macrosuch как это:

#define PrintDie(...) \ 
    do \ 
    { \ 
    fprintf(stderr, __VA_ARGS__); \ 
    abort(); \ 
    } while(0) 

Который затем позволяет запускать функцию как:

if(-1 == foo()) PrintDie("Oh no"); 

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

+1

Ваш 'PrintDie' должен вызывать' abort', а не 'exit'. Потому что было бы проще отлаживать (в Linux вы даже получите дамп 'core', который вы могли бы проанализировать посмертным с помощью' gdb') –

+0

@BasileStarynkevitch Спасибо, забыл все о прерывании, изменил пример использования это сейчас. – Vality

+1

'if (NULL == AllocMem)' неправильный тест. С 'MemSize == 0', получая' malloc() 'возвращаемое значение' NULL' _is_ совместимого поведения, а не сбой распределения. Переход на 'if (NULL == AllocMem && MemSize! = 0)' исправляет это. – chux

Смежные вопросы