безопасно 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