Per the standard, is it safe to take the address of malloc()
, realloc()
, and free()
?
For example,
#include <stdlib.h>
void * (*my_malloc)(size_t) = &malloc;
Corollary, is it possible in standards-compliant C that the implementation uses a macro for malloc
/realloc
/free
?
Yes, this is safe. The standard library is allowed to define function-like macros for any of its functions, but they must also be available as functions.
C17 7.1.4 (1)
Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro. [189]
[189] This means that an implementation shall provide an actual function for each library function, even if it also provides a macro for that function.
So in short, the library's header is allowed to have something like
void *malloc(size_t);
#define malloc(s) __fancy_internal_malloc((s) + 47 | 0x14 * 3)
and so then you can do any of
void *p = malloc(10); // invokes the macro if there is one
void *q = (malloc)(10); // definitely calls the function, not the macro
void *(*allocator)(size_t) = &malloc; // takes address of the function
#undef malloc
void *r = malloc(10); // definitely the function
Of course, the function and the macro must both provide whatever behavior the standard promises (though as Eric Postpischil comments, they do not have to behave identically so long as each is conformant). In particular, it must be safe to allocate with the macro and free with the function, or vice versa. Also, such a macro must evaluate each of its arguments exactly once, so p = malloc(s++);
is safe for either the function or the macro.