在 cpp 程序中覆盖 malloc 和新调用

override malloc and new calls in cpp program

我想调用我的自定义 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

这适用于 .c 文件的 gcc,但不适用于 g++ 和 .cpp 文件。有什么问题?

2. 另外我不知道如何覆盖新呼叫?

为什么 g++ 不能与 -Wl,--wrap,malloc 一起使用?

g++适用于C++,C++ ABI不同于C ABI。所以你需要在 __real_malloc__wrap_malloc:

周围添加 extern "C"
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”之前插入 _ name 在程序集中创建一个名称。 (此命名约定称为 _cdecl,最常用。)extern "C" 强制 C++ 编译器根据 C 的约定生成名称。有关详细信息,请参阅 https://en.wikipedia.org/wiki/Name_mangling

如何覆盖 new

您可以专门为 class 覆盖 new,或提供全局 new。参见 https://en.cppreference.com/w/cpp/memory/new/operator_new

如果您使用的是 glibc,那么您可以使用 malloc 的 GNU 扩展:man malloc_hook

   #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 自身,当发生这种情况时,很可能会出现无限递归。