c - Are the gcc memory hooks sometimes bypassed? -


for c++ arm application need trace memory allocations. using gcc memory hooks. printing allocations , deallocations, see code below.

however, malloc's , free's don't add up. see free on memory block pass through didn't malloc hook before. or memory freed twice. of course bug in code,although don't segfault. see malloc returns pointer has returned before , there has been no free in meantime (at least free hook wasn't called).

so guess malloc's , free's not passed through hooks. note when trace c++ allocations things add nicely.

does have ideas?

#include <stdlib.h> #include <stdio.h> #include <pthread.h> #include <new> #include <unistd.h> #include <string.h> #include <malloc.h>  pthread_mutex_t lock = pthread_recursive_mutex_initializer_np;  static void push_memhooks(); static void pop_memhooks();  static void *malloc_hook(size_t size, const void *ret) {      pthread_mutex_lock(&lock);      pop_memhooks();      void *mem = malloc(size);      if (mem) {         printf("malloc %p\n", mem);     }      push_memhooks();      pthread_mutex_unlock(&lock);      return mem; }  static void *realloc_hook(void* ptr, size_t size, const void *ret) {     pthread_mutex_lock(&lock);      pop_memhooks();      void* mem = realloc(ptr, size);      if (mem) {         printf("realloc %p -> %p\n", ptr, mem);     }      push_memhooks();      pthread_mutex_unlock(&lock);      return mem; }  static void* memalign_hook(size_t boundary, size_t size, const void *ret) {     pthread_mutex_lock(&lock);     pop_memhooks();      void* mem = memalign(boundary, size);      if (mem) {         printf("memalign %p\n", mem);     }      push_memhooks();      pthread_mutex_unlock(&lock);      return mem; }  static void free_hook(void *mem, const void *ret) {     pthread_mutex_lock(&lock);      pop_memhooks();      free(mem);      printf("free %p\n", mem);      push_memhooks();      pthread_mutex_unlock(&lock); }  void *operator new(size_t size) {     void* mem = malloc(size);      if (!mem) {         throw std::bad_alloc();     }      return mem; }  void operator delete(void* mem) {     free(mem); }  void *operator new[](size_t size) {            void* mem = malloc(size);      if (!mem) {         throw std::bad_alloc();     }      return mem; }  void operator delete[](void* mem) {     free(mem); }  static int memhooks = 0;  static void push_memhooks() {     if (++memhooks == 1) {         __malloc_hook = malloc_hook;         __realloc_hook = realloc_hook;         __free_hook = free_hook;         __memalign_hook = memalign_hook;     } }  static void pop_memhooks() {     if (--memhooks == 0) {         __malloc_hook = null;         __realloc_hook = null;         __free_hook = null;         __memalign_hook = null;     } }  static void install_memhooks () {     push_memhooks(); }  void (*__malloc_initialize_hook)(void) = install_memhooks; 

for example, following output when grep trace pointer shows strange behaviour.

<snip> malloc 0x8234818 free 0x8234818 malloc 0x8234818 malloc 0x8234818 free 0x8234818 <snip> 

notice 2 consecutive malloc's.

solution: chris mentioned in answer, there's race condition in code above. unfortunately, malloc hooks cannot safely used in multithreaded environment when removing , reinstalling hooks way do. same reason, mcheck cannot used in multithreaded apps (http://sources.redhat.com/bugzilla/show_bug.cgi?id=9939).

implementing malloc/realloc/free , calling libc versions using dlsym(rtld_next, "malloc") didn't work either. first, dlsym calls calloc, special care needed prevent infinite recursion here. second, when calling libc malloc, process hangs. furthermore, see __malloc_initialize_hook doesn't called. guess providing own malloc implementation, libc malloc isn't initialized.

my current solution has dlmalloc implementation embedded remove dependency on libc malloc. don't have continuously remove/reinstall malloc hooks. install hooks once , hooks allocate memory using dlmalloc.

if you're running in multithreaded environment, have race condition might cause miss calls malloc/free. when malloc_hook function called, unhooks hooks, calls malloc , rehooks hooks. if other thread calls malloc/free while hooks unhooked, won't see call. mutex doesn't help, while unhooked, malloc/free call won't call hook function, won't wait on mutex.

edit

my preferred way of hooking/intecepting malloc in program intercept calls program using macros, without worrying calls within stdlib. create wrap_malloc file with:

#define malloc(sz)     wrap_malloc(sz, __file__, __line__) #define free(p)        wrap_free(p, __file__, __line__) #define realloc(p, sz) wrap_realloc(p, sz, __file__, __line__) #define calloc(s1, s2) wrap_calloc(s1, s2, __file__, __line__) 

then compile code -imacros wrap_malloc. file defines wrap_malloc , friends needs appropriate #undefs, no other changes code needed.


Comments

Popular posts from this blog

android - Spacing between the stars of a rating bar? -

html - Instapaper-like algorithm -

c# - How to execute a particular part of code asynchronously in a class -