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
?
Let’s see how we use malloc () and free () functions. How do we use the malloc () function? malloc () function is a Dynamic Memory Allocation function that allocates a block of size bytes from the memory heap. It allows a program to allocate memory explicitly as it is needed, and in the exact amounts needed. The allocation is from the main memory.
As we can see, copying manually with memcpy is always slower than realloc, because in this scenario malloc is guaranteed to allocate new memory and you're forced to copy the data in every allocation, which shows us that realloc is indeed reusing the same address and enlarging the block size in some cases.
If the argument size == 0, malloc returns NULL. How can I use malloc () and free () functions? The free () function is a Dynamic Memory Allocation function that frees allocated block. Free () deallocates a memory block allocated by a previous call to calloc , malloc, or realloc.
realloc () function modifies the allocated memory size by malloc () and calloc () functions to new size. If memory is not sufficient for malloc () or calloc (), you can reallocate the memory by realloc () function.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With