Node:Hooks for Malloc, Next:Statistics of Malloc, Previous:Heap Consistency Checking, Up:Unconstrained Allocation
The GNU C library lets you modify the behavior of malloc
,
realloc
, and free
by specifying appropriate hook
functions. You can use these hooks to help you debug programs that use
dynamic memory allocation, for example.
The hook variables are declared in malloc.h
.
__malloc_hook | Variable |
The value of this variable is a pointer to the function that
malloc uses whenever it is called. You should define this
function to look like malloc ; that is, like:
void *function (size_t size, const void *caller) The value of caller is the return address found on the stack when
the |
__realloc_hook | Variable |
The value of this variable is a pointer to function that realloc
uses whenever it is called. You should define this function to look
like realloc ; that is, like:
void *function (void *ptr, size_t size, const void *caller) The value of caller is the return address found on the stack when
the |
__free_hook | Variable |
The value of this variable is a pointer to function that free
uses whenever it is called. You should define this function to look
like free ; that is, like:
void function (void *ptr, const void *caller) The value of caller is the return address found on the stack when
the |
__memalign_hook | Variable |
The value of this variable is a pointer to function that memalign
uses whenever it is called. You should define this function to look
like memalign ; that is, like:
void *function (size_t size, size_t alignment, const void *caller) The value of caller is the return address found on the stack when
the |
You must make sure that the function you install as a hook for one of these functions does not call that function recursively without restoring the old value of the hook first! Otherwise, your program will get stuck in an infinite recursion. Before calling the function recursively, one should make sure to restore all the hooks to their previous value. When coming back from the recursive call, all the hooks should be resaved since a hook might modify itself.
__malloc_initialize_hook | Variable |
The value of this variable is a pointer to a function that is called
once when the malloc implementation is initialized. This is a weak
variable, so it can be overridden in the application with a definition
like the following:
void (*__malloc_initialize_hook) (void) = my_init_hook; |
An issue to look out for is the time at which the malloc hook functions
can be safely installed. If the hook functions call the malloc-related
functions recursively, it is necessary that malloc has already properly
initialized itself at the time when __malloc_hook
etc. is
assigned to. On the other hand, if the hook functions provide a
complete malloc implementation of their own, it is vital that the hooks
are assigned to before the very first malloc
call has
completed, because otherwise a chunk obtained from the ordinary,
un-hooked malloc may later be handed to __free_hook
, for example.
In both cases, the problem can be solved by setting up the hooks from
within a user-defined function pointed to by
__malloc_initialize_hook
--then the hooks will be set up safely
at the right time.
Here is an example showing how to use __malloc_hook
and
__free_hook
properly. It installs a function that prints out
information every time malloc
or free
is called. We just
assume here that realloc
and memalign
are not used in our
program.
/* Prototypes for __malloc_hook, __free_hook */ #include <malloc.h> /* Prototypes for our hooks. */ static void *my_init_hook (void); static void *my_malloc_hook (size_t, const void *); static void my_free_hook (void*, const void *); /* Override initializing hook from the C library. */ void (*__malloc_initialize_hook) (void) = my_init_hook; static void my_init_hook (void) { old_malloc_hook = __malloc_hook; old_free_hook = __free_hook; __malloc_hook = my_malloc_hook; __free_hook = my_free_hook; } static void * my_malloc_hook (size_t size, const void *caller) { void *result; /* Restore all old hooks */ __malloc_hook = old_malloc_hook; __free_hook = old_free_hook; /* Call recursively */ result = malloc (size); /* Save underlying hooks */ old_malloc_hook = __malloc_hook; old_free_hook = __free_hook; /*printf
might callmalloc
, so protect it too. */ printf ("malloc (%u) returns %p\n", (unsigned int) size, result); /* Restore our own hooks */ __malloc_hook = my_malloc_hook; __free_hook = my_free_hook; return result; } static void * my_free_hook (void *ptr, const void *caller) { /* Restore all old hooks */ __malloc_hook = old_malloc_hook; __free_hook = old_free_hook; /* Call recursively */ free (ptr); /* Save underlying hooks */ old_malloc_hook = __malloc_hook; old_free_hook = __free_hook; /*printf
might callfree
, so protect it too. */ printf ("freed pointer %p\n", ptr); /* Restore our own hooks */ __malloc_hook = my_malloc_hook; __free_hook = my_free_hook; } main () { ... }
The mcheck
function (see Heap Consistency Checking) works by
installing such hooks.