tcmalloc: how can I get my malloc calls overridden when compiling statically?
Asked Answered
B

2

9

When I use LD_PRELOAD=/usr/local/lib/libtcmalloc.so, all my calls to malloc become tcmalloc calls. However, when I link statically against libtcmalloc, I find that straight malloc is getting called unless I still use the LD_PRELOAD setting.

So how can I statically compile against tcmalloc in such a way that my mallocs hook into tcmalloc?

Notes:

  • I'm using lots of C++ new etc, so just #defining malloc to tcmalloc won't work
  • Possibly I have to use malloc_hook myself, but I would have thought I could get tcmalloc to do it for me, since it clearly is doing it when linking dynamically
Bladderwort answered 12/10, 2009 at 8:50 Comment(0)
V
14

Symbols are resolved on a first match basis. You need to make sure that libtcmalloc.a is searched before libc.a by the linker. I assume that you are not explicitly linking libc.a since you do not normally need to do so. The solution is to specify -nostdlibs, and then explicitly link all necessary libraries in the order you want them to be searched. Usually something like:

-nostdlibs -llibtcmalloc -llibm -llibc -llibgcc

Another solution which may be simpler, is to link the object file(s) needed to resolve tcmalloc rather than the static library, since object files take precedence over libraries in resolving symbols.

Valtin answered 12/10, 2009 at 9:17 Comment(0)
P
2

TCMalloc overrides all allocation/deallocation function calls, including all variants of New/Delete, and C API (malloc/free/calloc/realloc/valloc/pvalloc/mem_aligned/malloc_usable_size) For gcc based platforms, it achieves the override using alias directive.

I'm using lots of C++ new etc, so just #defining malloc to tcmalloc won't work

In TCMalloc headers, malloc is already aliased to tc_malloc, so this has no effect. For example:

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

As for New, please note that unlike glibc and other implementation of New (windows), that just wrapps malloc, tcmalloc's New does not call malloc.

TCMalloc New is aliased to tc_new and tc_newarray, which will call TCMalloc's "magical" memory manager, and in some cases, as libc malloc, will initiate a sbrk/brk system call.

Another thing you need to do is make sure gcc does not link with libc's malloc variants. For this, please add to C++ Flags in the Makefile the following:

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

Also, don't forget to specify TCMalloc static library:

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

Possibly I have to use malloc_hook myself, but I would have thought I could get tcmalloc to do it for me, since it clearly is doing it when linking dynamically

TCMalloc does not use malloc_hooks, which is by now considered deprecated due to thread safety issues. It simply uses the fact that memory-allocation methods are weak symbols. It overrides those symbols either using aliases (in gcc) __attribute__((alias)) of by function calls.

Please refer to: https://github.com/gperftools/gperftools/blob/master/README

Piselli answered 25/4, 2018 at 12:38 Comment(2)
dynamically linking libtcmalloc doesn't seem to work with -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free . After linking LDD doesn't list libtcmalloc.so as one of the shared object dependency? @daniel Helper could you elaborate a bit more as to why this wouldn't be working?Molding
if tcmalloc header declared malloc to be an alias of tc_malloc, won't it conflict with another malloc declaration in the standard c++ headers?Recruit

© 2022 - 2024 — McMap. All rights reserved.