注意,以下方法對於多線程來說不管用。如,A線程調用到malloc_hook 函數,把malloc_hook函數還原爲libc malloc函數,此時B線程調用到malloc函數便是libc malloc函數,根本不會進入到我們的malloc_hook設定的my_malloc函數。因此,多線程下是不能使用此方法,需要用__wrap_malloc方式解決。
__malloc_hook是一組glibc提供的malloc調試變量中的一個,這組變量包括:
void *(*__malloc_hook)(size_t size, const void *caller);
void *(*__realloc_hook)(void *ptr, size_t size, const void *caller);
void *(*__memalign_hook)(size_t alignment, size_t size, const void *caller);
void (*__free_hook)(void *ptr, const void *caller);
void (*__malloc_initialize_hook)(void);
void (*__after_morecore_hook)(void);
何謂鉤子函數,當一個函數掛載了鉤子函數後,你執行這個函數時,實際執行的是鉤子函數
只要你在程序中寫上”__malloc_hook= my_malloc_hook;”,之後的malloc調用都會使用my_malloc_hook函數,方便易行。但是這組調試變量不是線程安全的,當你想用系統malloc的時候不得不把他們改回來,多線程調用就得上鎖。
#include <stdio.h>
#include <malloc.h>
#define THREAD_AUTOLOCK
static void (*old_free)(void *ptr, const void *caller);
static void *(*old_malloc)(size_t size, const void *caller);
static void my_free(void *ptr, const void *caller);
static void *my_malloc(size_t size, const void *caller);
static void hook_back()
{
old_malloc = __malloc_hook;
old_free = __free_hook;
}
static void hook_init()
{
__malloc_hook = my_malloc;
__free_hook = my_free;
}
static void hook_restore()
{
__malloc_hook = old_malloc;
__free_hook = old_free;
}
static void my_free(void *ptr, const void *caller)
{
THREAD_AUTOLOCK;
hook_restore();// 這裏必須,不然會死循環
printf("free address: %x\n", ptr);
free(ptr);
hook_init();
return;
}
static void *my_malloc(size_t size, const void *caller)
{
THREAD_AUTOLOCK;
void *p = NULL;
hook_restore();// 這裏必須,不然會死循環
printf("malloc size: %d\n", size);
p = malloc(size);
hook_init();
return p;
}
static void my_mempool_destroy()
{
hook_restore();
}
static void my_mempool_init()
{
hook_back();
hook_init();
atexit(my_mempool_destroy);
}
void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = my_mempool_init;
int main(int argc, char **argv)
{
void *p = malloc(12);
if (p != NULL)
free(p);
return 0;
}
int atexit(void(*func)(void));
#include<stdio.h>
#include<stdlib.h>
void func1(void)
{
printf("in func1\n");
}
void func2(void)
{
printf("in func2\n");
}
void func3(void)
{
printf("in func3\n");
}
int main()
{
atexit(func3);
atexit(func2);
atexit(func1);
printf("In main\n");
return 0;
}
exit()和_exit()以及_Exit()函數的本質區別是是否立即進入內核,_exit()以及_Exit()函數都是在調用後立即進入內核,而不會執行一些清理處理,但是exit()則會執行一些清理處理,這也是爲什麼會存在atexit()函數的原因,因爲exit()函數需要執行清理處理,需要執行一系列的操作,這些終止處理函數實際上就是完成各種所謂的清除操作的實際執行體。atexit函數的定義也給了程序員一種運用exit執行一些清除操作的方法,比如有一些程序需要額外的操作,具體的清除操作可以採用這種方法對特殊操作進行清除等。