mi-malloc 1.8/2.1
 
正在加载...
正在搜索...
无匹配项
覆盖 Malloc

覆盖标准 malloc (和 new) 可以通过动态静态方式完成。

动态覆盖

这是推荐的覆盖标准 malloc 接口的方式。

Linux、BSD 上的动态覆盖

在这些基于 ELF 的系统上,我们预加载 mimalloc 共享库,因此对标准 malloc 接口的所有调用都将解析到 mimalloc 库。

> env LD_PRELOAD=/usr/lib/libmimalloc.so myprogram

您可以设置额外的环境变量来检查 mimalloc 是否正在运行,例如

> env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogram

或者运行调试版本以获取详细统计信息

> env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram

macOS 上的动态覆盖

在 macOS 上,我们也可以预加载 mimalloc 共享库,因此对标准 malloc 接口的所有调用都将解析到 mimalloc 库。

> env DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram

请注意,从shell 执行此操作时,可能会受到某些安全限制。

Windows 上的动态覆盖

在 Windows 上动态覆盖 mimalloc 是可靠的,并且具有能够重定向所有通过(动态)C 运行时分配器进行的 malloc/free 调用的特殊优点,包括来自其他 DLL 或库的调用。由于它在低级别拦截所有分配调用,因此它可以可靠地用于包含其他第三方组件的大型程序。要使覆盖正常工作,需要满足四个要求:

  1. 将 C 运行时库用作 DLL(使用 /MD/MDd 开关)。
  2. 将程序显式链接到 mimalloc.dllmimalloc.lib 导出库。(尽管默认情况下,必须使用 -DMI_OVERRIDE=ON 编译此库)。为了确保 mimalloc.dll 在运行时实际加载,最简单的方法是在 main 函数中插入对 mimalloc API 的一些调用,例如 mi_version()(或在链接器命令上使用 /include:mi_version 开关,或类似地,在某个源文件中使用 #pragma comment(linker, "/include:mi_version"))。有关如何使用此功能的示例,请参阅 mimalloc-test-override 项目。
  3. mimalloc-redirect.dll 在运行时必须与主 mimalloc.dll 放在同一目录中(因为它是一个依赖项)。重定向 DLL 确保所有对 C 运行时 malloc API 的调用都被重定向到 mimalloc 函数(它们位于 mimalloc.dll 中)。
  4. 确保 mimalloc.dll 尽可能早地出现在最终可执行文件的导入列表中(这样它就可以拦截所有潜在的分配)。如果需要,您可以使用 minject -l 进行检查。

为了在 Windows 上使用 C++ 获得最佳性能,还建议覆盖 new/delete 操作(通过在项目中包含一个mimalloc-new-delete.h 单个(!)源文件)。

环境变量 MIMALLOC_DISABLE_REDIRECT=1 可用于在运行时禁用动态覆盖。使用 MIMALLOC_VERBOSE=1 来检查 mimalloc 是否成功重定向。

对于 x64 以外的平台,您可能需要特定的 [重定向 dll](bin)。此外,我们不能总是重新链接可执行文件或确保 mimalloc.dll 在导入表中排在第一位。在这种情况下,可以使用 [minject](bin) 工具来修补可执行文件的导入表。

静态覆盖

在类 Unix 系统上,您还可以静态链接 mimalloc 来覆盖标准 malloc 接口。推荐的方法是将最终程序与 mimalloc 单个目标文件 (mimalloc.o) 链接。我们使用目标文件而不是库文件,因为链接器优先于归档文件解析符号。为了确保标准 malloc 接口解析到 mimalloc 库,请将其作为第一个目标文件链接。例如

> gcc -o myprogram mimalloc.o myfile1.c ...

另一种适用于所有平台的静态覆盖方式是静态链接到 mimalloc(如简介所示),并在每个源文件中包含一个头文件,将 malloc 等重新定义为 mi_malloc。这由 mimalloc-override.h 提供。但这仅在所有源文件都在您的控制之下时才能可靠地工作,否则可能会发生来自不同堆的指针混合!

覆盖列表

重定向到 mimalloc 库的特定函数是

// 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);