Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the following program a strictly-conforming C99 program?

Tags:

c

The title nearly says it all, but I will restate the question...

Is the following program a "strictly conforming program" under the C99 standard?

#include <stdlib.h>
/* Removing any pre-existing macro definition, in case one should exist in the implementation.
 * Seems to be allowed under 7.1.3 para 3, as malloc does not begin with _X where X is any  capital letter.
 * And 7.1.4 para 1 explicitly permits #undef of such macros.
 */
#ifdef malloc    
#undef malloc     
#endif            

/* Macro substitution has no impact on the external name malloc
 * which remains accessible, e.g., via "(malloc)(s)".  Such use of
 * macro substitution seems enabled by 7.1.4 para 1, but not specifically
 * mentioned otherwise.
 */
void * journalling_malloc(size_t size);
#define malloc(s)     ((journalling_malloc)(s))      

int main(void)
{
    return malloc(10) == NULL ? 1 : 0;     
    /* Just for the sake of expanding the 
     * macro one time, return as exit code
     * whether the allocation was performed. 
     */
}
like image 986
Heath Hunnicutt Avatar asked Feb 15 '10 18:02

Heath Hunnicutt


2 Answers

Let's look at what the C99 standard has to say about it:

See 7.1.3, §1, clause 5:

Each identifier with file scope listed in any of the following subclauses [...] is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.

As you include stdlib.h, the name malloc is reserved for use as a macro name.

But 7.1.4, §1 allows using #undef on reserved names:

The use of #undef to remove any macro definition will also ensure that an actual function is referred to.

This makes it possible to re-#define malloc, which results in undefined behaviour according to 7.1.3, §2:

If the program [...] defines a reserved identifier as a macro name, the behavior is undefined.

Why does the standard make this restriction? Because other functions of the standard library may be implemented as function-like macros in terms of the original function, so hiding the declaration might break these other functions.

In practice, you should be fine as long as your definition of malloc satisfies all provisions the standard provides for the library function, which can be achieved by wrapping an actual call to malloc().

like image 162
Christoph Avatar answered Oct 05 '22 18:10

Christoph


You will want to change journalling_malloc(...) from void to void *, change the comments to // (because they are commenting out your undef) and add a #endif near the top, but otherwise it looks fine.

like image 38
DigitalRoss Avatar answered Oct 05 '22 18:10

DigitalRoss