Recently with the help of Moinak and Kishore I wrote a wrapper library which dumps memory leaks.
Thought of talking about it here.
You can use libumem to identify memory leaks.
I feel libumem is a powerful tool to identify memory leaks.
The tool we developed is a simple one and just only done for learning stuff.
Idea was to write a wrapper library which we can just preload it to the app.
What the idea was to track all memory allocations which are not freed.
atexit, registered reportalloc (function which reports allocation), so on program termination
we get the dump of all memory allocations which are not freed. Not only I report
at the exit, we can also get a dump of all allocations when a particular signal is sent to
the program. You can set an environment variable SIGNAL_USED to a signal which is unused
in the program (How do you find which signals don't have handlers...use psig on the process).
wrapper library will handle that signal, so when ever you send a signal $SIGNAL_USED
to the process it dumps all allocations at that instance.
We wrote wrappers for malloc, calloc, realloc, valloc and free.
How we got stack trace? We got the stack frames and extracted return addresses and
using dladdr to find symbolic information.
Some codesnips of the library is below.
Only writng malloc here as other are almost similar except calloc which has an extra argument.
void *malloc(size_t size) {
void *buf;
/* dlinit will initialize global function pointers which will
* point to the original libc functions.
*/
dlinit();
/* mptr is a function pointer to libc malloc */
buf = (*mptr)(size);
/* We add the data to a hashed list
* what each node in the hashed chain contains
* is the address returned, stack trace, bytes allocated
*/
addnode(buf, size);
return (buf);
}
void dlinit(void) {
/* lock it so that multiple threads in application might not simultaniously
* do a dlopen
*/
pthread_mutex_lock(&mt);
if (dlh == NULL) {
if ( (dlh = dlopen("libc.so", RTLD_NOW|RTLD_PARENT))
== NULL) {
perror("dlopen: ");
pthread_mutex_unlock(&mt);
exit(1);
}
/* get pointers for malloc, calloc,... etc */
mptr = (void *(*)(size_t))dlsym(dlh, "malloc");
cptr = (void *(*)(size_t, size_t))dlsym(dlh, "calloc");
rptr = (void *(*)(void *, size_t))dlsym(dlh, "realloc");
vptr = (void *(*)(size_t))dlsym(dlh, "valloc");
malignptr = (void *(*)(size_t, size_t))dlsym(dlh, "memalign");
fptr = (void (*)(void *))dlsym(dlh, "free");
/* register signal handler*/
sigact.sa_handler = sighandler;
if (sigaction(SIGNAL_USED, &sigact, NULL)) {
perror("failed in registering signal");
}
atexit(report);
}
pthread_mutex_unlock(&mt);
}
...
...
...
void sighandler(void) {
pthread_t thr;
/* create a new thread and dump current allocations which are not freed. */
pthread_create(&thr, NULL, reportallocs, NULL);
pthread_detach(thr);
}
Trackback URL: http://blogs.sun.com/popuri/entry/wrapper_library_to_track_memory
Posted by gorank on June 23, 2005 at 06:36 PM IST #