Returning from a Macro

        Submitter: Muli Ben-Yehuda

        Language: C

        Date:        2003/07/04

Witness this innocent chunk of code, from fs/intermezzo/journal.c in a Linux kernel tree near you [at least until it's fixed - OG]:

#define BUFF_ALLOC(newbuf, oldbuf) \
PRESTO_ALLOC(newbuf, PAGE_SIZE); \
if ( !newbuf ) { \
if (oldbuf) \
BUFF_FREE(oldbuf); \
return -ENOMEM; \
}

Do I really need to explain why returning from a macro is a bad, bad, bad, god-awful idea? Consider:
void foo(void)
{
void* buf1, buf2, buf3;

BUFF_ALLOC(buf1, NULL);
BUFF_ALLOC(buf2, buf1);

BUFF_ALLOC(buf3, buf2); <----- BOOOM. Bye bye buf1 memory
if allocation fails.
}

Resource allocation and deallocation should always be handled with care. Sequence points where resource book keeping is required must be explicit. So I have spoken. Muli the weary.

-----------------------------------------------

Oleg Goldshmidt:

The macro has so many problems - side effects on both buffers, control flow elements (if, return), memory allocation and deallocation - that the author should be chained to a tech support desk for at least a few years. How the hell did Linus let it through? Shuddddderrrrr.