With Linux/GCC/C++, I'd like to record something to stderr whenever malloc/free/new/delete are called. I'm trying to understand a library's memory allocations, and so I'd like to generate this output while I'm running unit tests. I use valgrind for mem leak detection, but I can't find an option to make it just log allocations.
Any ideas? I'm looking for the simplest possible solution. Recompiling the library is not an option.
malloc_hook(3)
allows you to globally interpose your own malloc
function. (There's __realloc_hook
__free_hook
etc. as well, I've just left them out for simplicity.)
#include <stdio.h>
#include <malloc.h>
static void *(*old_malloc_hook)(size_t, const void *);
static void *new_malloc_hook(size_t size, const void *caller) {
void *mem;
__malloc_hook = old_malloc_hook;
mem = malloc(size);
fprintf(stderr, "%p: malloc(%zu) = %p\n", caller, size, mem);
__malloc_hook = new_malloc_hook;
return mem;
}
static void init_my_hooks(void) {
old_malloc_hook = __malloc_hook;
__malloc_hook = new_malloc_hook;
}
void (*__malloc_initialize_hook)(void) = init_my_hooks;
$ cat >mem.c <<'EOF'
(the code above)
EOF
$ cc -fPIC -shared -o mem.so mem.c
$ LD_PRELOAD=./mem.so ls
0x7ffc14931adc: malloc(5) = 0xb40010
0x7ffc1492c6b0: malloc(120) = 0xb40030
0x7ffc1497f61a: malloc(12) = 0xb40010
0x7ffc1492be38: malloc(776) = 0xb400b0
…
printf
might call malloc
, which is why we undo the hook temporarily. Be careful of this if when you hook malloc
in any way.
You can trace calls to malloc/free with ltrace:
#include <stdlib.h>
int main (void)
{
void *ptr = malloc(10);
free(ptr);
return 0;
}
$ g++ test.cpp -o test
$ ltrace -e malloc,free ./test
malloc(10) = 0x804a008
free(0x804a008) = <void>
+++ exited (status 0) +++
To trace new/delete calls without recompiling you will probably need to use something like LD_PRELOAD to override the calls with your own versions, this is precisely what LeakTracer does which might do what you want.
This article (scroll down to the bottom) provides a very clear and concise description of how to override the global new
and delete
operators in C++ (note that it doesn't provide an example for new[]
, but it's similar in concept).
As far as overriding malloc and free, since you're working on Linux and with GCC, the easiest method is to use malloc_hook
and free_hook
. Here is a very good description of how these functions work.
I have not tested this myself, but I am pretty sure these would work:
Since you do not want to re-compile the library, giving meaningful output (vs. just "new called for 23 bytes") may require getting a stack trace. I remember using functions to navigate the stack, but I cannot find them right now. Maybe a call to system() and pstack(1) can do the trick.
You can re-define operator new and delete, and put this new definition ahead of the std c++ library. This may not capture the calls from containers and standard components that the library in question is using. This would require a relink.
Use can use LD_PRELOAD to change operator new and delete dynamically. This would not require a re-link if your application is dynamically linked.
Hope these pointers help, I am sorry I do not have a recipe.