c++ 覆盖cpp程序中的malloc和新调用

k2arahey  于 2023-05-02  发布在  其他
关注(0)|答案(4)|浏览(205)

我想调用我的自定义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 for。c文件,但不与g++和.cpp文件有什么问题

**2.**我也不知道如何覆盖新的呼叫?

jljoyd4f

jljoyd4f1#

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

如何覆盖new

您可以专门为某个类重写new,或提供全局new。参见https://en.cppreference.com/w/cpp/memory/new/operator_new

2uluyalo

2uluyalo2#

如果你正在使用glibc,那么你可以使用malloc的GNU扩展:人用马洛克钩

#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

ylamdve6

ylamdve63#

其他答案说明了为什么-Wl,--wrap,malloc不起作用。
但是请注意,在你使它工作之后,你的代码很可能由于堆栈溢出而崩溃。
这是因为printf可以(并且在某些情况下确实)调用malloc本身,当这种情况发生时,很可能会出现无限递归。

htrmnn0y

htrmnn0y4#

如果有人想知道如何覆盖所有的分配器函数,Here is a list的所有函数,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

因此,为了覆盖所有相关函数,自定义这些条目可能是另一种解决问题的好方法。

相关问题