Reputation: 1383
I want to understand how memory tracker and leak detector work, so I come with this idea, I have an executable, and I want to force it while execution to use my own memory allocation functions instead of the usual system functions ("malloc", "realloc"...).
My own functions are stored in a library (static or shared) or just an object file (".o"), thik about something like that:
void *my_own_malloc(unsigned long size) {
printf("allocate: %lu\n", size);
return malloc(size);
}
PS: I don't have to change the executable source code (I don't have source code)
PS2: I want to do that in all different platform (Windows, OS X & Linux...)
Upvotes: 3
Views: 813
Reputation: 3816
I don't know about the other platforms, but on GNU/Linux you could pre-load a small memory tracking library with the LD_PRELOAD
environment variable in which your own malloc
and free
are defined.
Your own malloc
would probably want to allocate memory using the real malloc
function, so there's a possible recursive problem here. To work around this, the dlsym function can use an RTLD_NEXT
argument to obtain the pointer to the next (i.e. the 'real') malloc
function.
A very small test of this could look like the following:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
void *malloc(size_t size)
{
static void *(*real_malloc)(size_t size) = 0;
if (!real_malloc)
real_malloc = dlsym(RTLD_NEXT, "malloc");
void *result = real_malloc(size);
fprintf(stderr, "malloc(%d) = %p\n", (int)size, result);
return result;
}
void free(void *ptr)
{
static void (*real_free)(void *ptr) = 0;
if (!real_free)
real_free = dlsym(RTLD_NEXT, "free");
real_free(ptr);
fprintf(stderr, "free(%p)\n", ptr);
}
If we call this file fakemalloc.c
, it can be compiled into a fakemalloc.so
shared object with the command
gcc -fPIC -shared -Wl,-soname,fakemalloc.so -o fakemalloc.so fakemalloc.c -ldl
As a test, to see which malloc
and free
calls happen in a call to the ls
command, you'd need to execute
LD_PRELOAD=/path/to/fakemalloc.so ls
EDIT: As mentioned in a comment, on glibc-systems you can avoid the RTLD_NEXT
approach by using the functions __libc_malloc
and __libc_free
. This would produce the following code:
#include <stdio.h>
void *__libc_malloc(size_t size);
void *__libc_free(void *ptr);
void *malloc(size_t size)
{
void *result = __libc_malloc(size);
fprintf(stderr, "malloc(%d) = %p\n", (int)size, result);
return result;
}
void free(void *ptr)
{
__libc_free(ptr);
fprintf(stderr, "free(%p)\n", ptr);
}
Upvotes: 4