取malloc()、realloc()和free()的地址是否可移植?
Is it portable to take the address of malloc(), realloc() and free()?
根据标准,使用 malloc()
、realloc()
和 free()
的地址安全吗?
例如,
#include <stdlib.h>
void * (*my_malloc)(size_t) = &malloc;
推论,在符合标准的 C 中,实现是否可能使用 malloc
/realloc
/free
的宏?
是的,这是安全的。允许标准库为其任何函数定义 function-like 宏,但它们也必须作为函数可用。
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.
所以简而言之,图书馆的 header 允许有类似
的内容
void *malloc(size_t);
#define malloc(s) __fancy_internal_malloc((s) + 47 | 0x14 * 3)
然后你可以做任何
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
当然,函数和宏都必须提供标准承诺的任何行为(尽管正如 Eric Postpischil 评论的那样,只要它们符合标准,它们的行为就不必相同)。特别是,使用宏分配和使用函数释放必须是安全的,反之亦然。此外,这样的宏必须对它的每个参数只计算一次,因此 p = malloc(s++);
对于函数或宏都是安全的。
根据标准,使用 malloc()
、realloc()
和 free()
的地址安全吗?
例如,
#include <stdlib.h>
void * (*my_malloc)(size_t) = &malloc;
推论,在符合标准的 C 中,实现是否可能使用 malloc
/realloc
/free
的宏?
是的,这是安全的。允许标准库为其任何函数定义 function-like 宏,但它们也必须作为函数可用。
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.
所以简而言之,图书馆的 header 允许有类似
的内容void *malloc(size_t);
#define malloc(s) __fancy_internal_malloc((s) + 47 | 0x14 * 3)
然后你可以做任何
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
当然,函数和宏都必须提供标准承诺的任何行为(尽管正如 Eric Postpischil 评论的那样,只要它们符合标准,它们的行为就不必相同)。特别是,使用宏分配和使用函数释放必须是安全的,反之亦然。此外,这样的宏必须对它的每个参数只计算一次,因此 p = malloc(s++);
对于函数或宏都是安全的。