безопасный malloc/realloc: перенос вызова в макрос?

Я хотел бы обернуть мои вызовы malloc/realloc в макрос, который остановит программу, если метод вернет NULL

я могу безопасно использовать следующий макрос?

#define SAFEMALLOC(SIZEOF) (malloc(SIZEOF) || (void*)(fprintf(stderr,"[%s:%d]Out of memory(%d bytes)\n",__FILE__,__LINE__,SIZEOF),exit(EXIT_FAILURE),0))
char* p=(char*)SAFEMALLOC(10);

он компилируется, он работает здесь с SAFEMALLOC(1UL) и SAFEMALLOC(-1UL), но это безопасный способ сделать это?


person Pierre    schedule 30.04.2013    source источник
comment
Почему макрос, а не функция? Таким образом, вы действительно можете заставить выражение возвращать полезный результат.   -  person CB Bailey    schedule 30.04.2013
comment
Обратите внимание, что SIZEOF оценивается дважды, когда вызов терпит неудачу (не катастрофа, поскольку программа завершает работу, но все же...).   -  person Kninnug    schedule 30.04.2013
comment
приведение результата не сделает его безопаснее, хотя...   -  person wildplasser    schedule 30.04.2013
comment
это не мои источники, я хотел бы избежать создания некоторых новых файлов (memory.c, memory.h), и я знаю, что автор хочет избежать некоторых вызовов других функций (микрооптимизация для научной программы на C)   -  person Pierre    schedule 30.04.2013


Ответы (2)


Нет, он сломан.

Кажется, предполагается, что логическое значение или оператор || возвращает свой аргумент, если он считается истинным, но это не так.

Логические операторы C всегда генерируют 1 или 0 как целые числа, они не генерируют какие-либо входные значения.

person unwind    schedule 30.04.2013
comment
true и false — это макросы в C99, которые вы можете включить в stdbool.h. Результатом || по-прежнему является int в C99. - person CB Bailey; 30.04.2013

Используя ваш макрос:

#define SAFEMALLOC(SIZEOF) (malloc(SIZEOF) || (void*)(fprintf(stderr,"[%s:%d]Out of memory(%d bytes)\n",__FILE__,__LINE__,SIZEOF),exit(EXIT_FAILURE),0))

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

int main(void)
{
    char *p = SAFEMALLOC(10);
    char *q = SAFEMALLOC(2000);

    printf("p = %p, q = %p\n", p, q);

    // Leak!
    return 0;
}

Предупреждения (должна быть подсказка):

weird.c:8: warning: cast to pointer from integer of different size
weird.c:8: warning: initialization makes pointer from integer without a cast
weird.c:9: warning: cast to pointer from integer of different size
weird.c:9: warning: initialization makes pointer from integer without a cast

Выход:

p = 0x1, q = 0x1

В общем, нет, это не очень безопасно! Написание функции, вероятно, будет менее подвержено ошибкам.

person CB Bailey    schedule 30.04.2013
comment
я бы бросил (char*) . Но теперь я не понимаю, почему p и q возвращают 0x1! Это тот же адрес/указатель, не так ли? :-) - person Pierre; 30.04.2013
comment
@Pierre: Нет, вы не должны приводить к char*; это скрыло бы предупреждение о том, что что-то не так! - person CB Bailey; 30.04.2013
comment
@Pierre Но теперь я не понимаю, почему p и q возвращают 0x1! -- Это потому, что вы не сделали даже самой элементарной работы по пониманию языка, на котором программируете. Значение (x || y) всегда либо 0, либо 1. - person Jim Balter; 30.04.2013
comment
@Pierre Что касается слепков, хорошие программисты относятся к ним как к рентгену или антибиотикам ... их следует использовать только в случае крайней необходимости. - person Jim Balter; 30.04.2013