我想调用我的自定义 malloc/new 调用而不是标准库函数。 1.对于malloc,我有这个简短的程序
#include <stdio.h>
#include <stdlib.h>
void *__real_malloc(size_t size);
void *__wrap_malloc(size_t size)
{
void *ptr = __real_malloc(size);
printf("malloc(%ld) = %p\n", size, ptr);
return ptr;
}
int main(void) {
int* ptr = (int*) malloc(sizeof(int));
return 0;
}
我使用以下命令来编译
g++ -Wl,--wrap,malloc main.cpp
但低于错误
/usr/bin/ld: /tmp/ccnB04KY.o: in function `__wrap_malloc(unsigned long)':
b3.cpp:(.text+0x18): undefined reference to `__real_malloc(unsigned long)'
/usr/bin/ld: /tmp/ccnB04KY.o: in function `main':
b3.cpp:(.text+0x54): undefined reference to `__wrap_malloc'
collect2: error: ld returned 1 exit status
这适用于 gcc 的 .c 文件,但不适用于 g++ 和 .cpp 文件。有什么问题吗?
2. 另外,我不知道如何覆盖新呼叫?
g++
不能与 -Wl,--wrap,malloc
一起使用?g++
意味着 C++,C++ ABI 与 C ABI 不同。所以你需要在 extern "C"
和 __real_malloc
周围添加 __wrap_malloc
:
extern "C" {
void *__real_malloc(size_t size);
void *__wrap_malloc(size_t size) {
void *ptr = __real_malloc(size);
printf("malloc(%ld) = %p\n", size, ptr);
return ptr;
}
}
为了避免冲突,C++ 编译器将名称重写为“随机”(但事实并非如此)字符串。这称为“名称修改”,它对有关命名空间、函数参数的信息进行编码(因为您可以在 C++ 中重载函数,并且链接器需要每个函数都有唯一的名称)等。相比之下,C 编译器无需将名称翻译为程序集。变化很大。 此编译器资源管理器示例显示 x86 msvc 编译器在函数名称前插入 _
,而其他 3 个编译器(x64 msvc、x86-64 gcc 和 x86-64 clang)保留 C 中定义的原始名称。
-Wl,--wrap,malloc
是传递给链接器的选项,它要求链接器查找名为
__wrap_malloc
的函数。使用 extern "C"
,g++ 会生成名称,就像在 C 源文件中定义该函数一样,以便链接器可以找到它。如何覆盖new
new
,或提供全局
new
。请参阅https://en.cppreference.com/w/cpp/memory/new/operator_new。
#include <malloc.h>
void *(*__malloc_hook)(size_t size, const void *caller);
void *(*__realloc_hook)(void *ptr, size_t size, const void *caller);
void *(*__memalign_hook)(size_t alignment, size_t size,
const void *caller);
void (*__free_hook)(void *ptr, const void *caller);
void (*__malloc_initialize_hook)(void);
void (*__after_morecore_hook)(void);
对于
new
,您可以提供全球新的。请参阅
https://en.cppreference.com/w/cpp/memory/new/operator_new。
-Wl,--wrap,malloc
不起作用。
但请注意,在你让它工作后,你的代码很可能由于堆栈溢出而崩溃。 这是因为
printf
可以(并且在某些条件下)调用
malloc
本身,当这种情况发生时,很可能会出现无限递归。mimalloc(MIT 许可证)覆盖的所有函数的列表:
// C
void* malloc(size_t size);
void* calloc(size_t size, size_t n);
void* realloc(void* p, size_t newsize);
void free(void* p);
void* aligned_alloc(size_t alignment, size_t size);
char* strdup(const char* s);
char* strndup(const char* s, size_t n);
char* realpath(const char* fname, char* resolved_name);
// C++
void operator delete(void* p);
void operator delete[](void* p);
void* operator new(std::size_t n) noexcept(false);
void* operator new[](std::size_t n) noexcept(false);
void* operator new( std::size_t n, std::align_val_t align) noexcept(false);
void* operator new[]( std::size_t n, std::align_val_t align) noexcept(false);
void* operator new ( std::size_t count, const std::nothrow_t& tag);
void* operator new[]( std::size_t count, const std::nothrow_t& tag);
void* operator new ( std::size_t count, std::align_val_t al, const std::nothrow_t&);
void* operator new[]( std::size_t count, std::align_val_t al, const std::nothrow_t&);
// Posix
int posix_memalign(void** p, size_t alignment, size_t size);
// Linux
void* memalign(size_t alignment, size_t size);
void* valloc(size_t size);
void* pvalloc(size_t size);
size_t malloc_usable_size(void *p);
void* reallocf(void* p, size_t newsize);
// macOS
void vfree(void* p);
size_t malloc_size(const void* p);
size_t malloc_good_size(size_t size);
// BSD
void* reallocarray( void* p, size_t count, size_t size );
void* reallocf(void* p, size_t newsize);
void cfree(void* p);
// NetBSD
int reallocarr(void* p, size_t count, size_t size);
// Windows
void* _expand(void* p, size_t newsize);
size_t _msize(void* p);
void* _malloc_dbg(size_t size, int block_type, const char* fname, int line);
void* _realloc_dbg(void* p, size_t newsize, int block_type, const char* fname, int line);
void* _calloc_dbg(size_t count, size_t size, int block_type, const char* fname, int line);
void* _expand_dbg(void* p, size_t size, int block_type, const char* fname, int line);
size_t _msize_dbg(void* p, int block_type);
void _free_dbg(void* p, int block_type);
这些覆盖被重定向到mimalloc/src/alloc-override.c
中的 mimalloc 库。一些重要的功能是:
mi_malloc
mi_calloc
mi_realloc
mi_reallocarr
mi_reallocf
mi_reallocarray
mi_valloc
mi_free
mi_free_aligned
mi_cfree
mi_new
mi_new_nothrow
mi_new_aligned
mi_new_aligned_nothrow
mi_posix_memalign
mi_memalign
mi_aligned_alloc
mi_pvalloc
因此,要覆盖所有相关功能,自定义这些条目可能是另一个好方法。