9

当我使用 时LD_PRELOAD=/usr/local/lib/libtcmalloc.so,我对 malloc 的所有调用都变成了 tcmalloc 调用。但是,当我静态链接 libtcmalloc 时,我发现直接 malloc 被调用,除非我仍然使用该LD_PRELOAD设置。

那么我怎样才能静态编译 tcmalloc 以使我的 malloc 挂钩到 tcmalloc 呢?

笔记:

  • 我使用了很多 C++ 新的等,所以只是 #defining malloc 到 tcmalloc 是行不通的
  • 可能我必须自己使用 malloc_hook,但我原以为我可以让 tcmalloc 为我做这件事,因为它显然是在动态链接时做的
4

2 回答 2

13

符号在第一次匹配的基础上被解析。您需要确保链接器在 libc.a之前搜索libtcmalloc.a。我假设您没有明确链接 libc.a,因为您通常不需要这样做。解决方案是指定 -nostdlibs,然后按照您希望搜索它们的顺序显式链接所有必要的库。通常是这样的:

-nostdlibs -llibtcmalloc -llibm -llibc -llibgcc

另一个可能更简单的解决方案是链接解析 tcmalloc 所需的目标文件而不是静态库,因为在解析符号时目标文件优先于库。

于 2009-10-12T09:17:51.233 回答
1

TCMalloc 覆盖所有分配/释放函数调用,包括New / Delete的所有变体和 C API ( malloc / free / calloc / realloc / valloc / pvalloc / mem_aligned / malloc_usable_size ) 对于基于 gcc 的平台,它使用别名指令实现覆盖。

我使用了很多 C++ 新的等,所以只是 #defining malloc 到 tcmalloc 是行不通的

在 TCMalloc 标头中,malloc已经别名为tc_malloc,所以这没有效果。例如:

#define ALIAS(tc_fn)   __attribute__ ((alias (#tc_fn), used))
void* malloc(size_t size) __THROW               ALIAS(tc_malloc)

至于New,请注意,与 glibc 和其他New (windows) 的实现不同,它只是包装了 malloc,tcmalloc 的 New 不调用 malloc。

TCMalloc New别名为tc_newtc_newarray,它们将调用 TCMalloc 的“神奇”内存管理器,并且在某些情况下,作为 libc malloc,将启动 sbrk/brk 系统调用。

您需要做的另一件事是确保 gcc 不与 libc 的 malloc 变体链接。为此,请在 Makefile 中的 C++ 标志中添加以下内容:

-fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free

另外,不要忘记指定 TCMalloc 静态库:

LIB_TCMALLOC = $(TCMALLOC_LIB_DIR)/libtcmalloc_minimal.a
LIB_DIR := .... -L$(TCMALLOC_LIB_DIR) ...
LIBS := ... -static $(LIB_TCMALLOC) ...

可能我必须自己使用 malloc_hook,但我原以为我可以让 tcmalloc 为我做这件事,因为它显然是在动态链接时做的

TCMalloc 不使用 malloc_hooks,由于线程安全问题,它现在被认为已弃用。它只是利用了内存分配方法是弱符号的事实。__attribute__((alias))它通过函数调用使用别名(在 gcc 中)覆盖这些符号。

请参考: https ://github.com/gperftools/gperftools/blob/master/README

于 2018-04-25T12:38:19.257 回答