1. tcmalloc程序启动后会设置内存分配hook与内存释放hook
(1)在HeapLeakChecker::BeforeConstructorsLocked();函数中设置了Hook,如下图:
上面设置的是内存分配与释放时该调用的Hook,在HeapProfilerStart函数中还设置了其它几个Hook,如下图,暂时还没研究是干啥用的。
(2)以AddNewHook为例,说明Hook的后续操作
该函数底层会调用如下语句:
通过这个语句,把Hook加入了new_hooks链表。
AddDeleteHook则是把Hook加入delete_hooks链表
(3)在HeapLeakChecker_BeforeConstructors函数中,通过判断need_heap_check是否为true,从而决定是否调用HeapLeakChecker::BeforeConstructorsLocked()函数,进而设置hook。
在该函数中根据读取环境变量"HEAPCHECK"的相关信息,从而设置need_heap_check
2.每次分配或者释放内存时,就会调用相应的hook
如下图,tc_malloc函数中调用了InvokNewHook(Invoke:调用)
InvokeNewHookSlow会继而调用函数INVOKE_HOOKS(NewHook, new_hooks_, (p, s));这个函数就相当于是调用前面设置的hook函数了。
3.NewHook,DeleteHook与内存泄露检查
NewHook把每次内存分配的信息(分配内存大小等信息)记入一系列的数据结构中,而DeleteHook则会清除对应的信息。内存泄露检查则是通过检查这些数据结构来发现是否有内存泄露。
注意:这里的hook貌似不是我之前windows编程中接触到的hook,这里的hook就是一个对自定义的函数的调用
4.调用栈信息是如何打印出来的?(这个代码按照“tcmalloc对照”说明)
4.1每次分配内存时,会调用NewHook,
该函数会先获得调用栈信息,然后再保存,调用栈信息函数如下:
其底层会有如下形式的调用:
找到get_stack_impl是什么,发现
发现get_stack_impl只是一个接口而已,在不同的系统有不同的定义。到这里,我们以impl_generic为例进行说明。现在我们要找到impl_generic是什么东西,但是直接搜索这个单词找不到它在哪里被定义。所以接下来看HAVE_GST_generic在哪里被定义,发现在如下的位置:
进入” stacktrace_impl_setup-inl.h”头文件与” stacktrace_generic-inl.h”头文件
” stacktrace_impl_setup-inl.h”头文件中有语句
而在上图中有”#define GST_SUFFIX generic”。而函数SIS_CONCAT是连接函数,所以在这里就得到了impl_generic。
4.2impl_generic是如何被定义的
” stacktrace_impl_setup-inl.h”头文件中有GET_STACK_TRACE_OR_FRAMES的宏定义,SIS_CONCAT只是连接两个字符串的函数。
然后”stacktrace_generic-inl.h”头文件中有该宏的使用,如下:
这两结合,就相当于定义了四个函数,即
SIS_CONCAT(GetStackFrames_, GST_SUFFIX),
SIS_CONCAT(GetStackFramesWithContext_,GST_SUFFIX),
SIS_CONCAT(GetStackTrace_, GST_SUFFIX),
SIS_CONCAT(GetStackTraceWithContext_,GST_SUFFIX),
当GST_SUFFIX= generic,这四个函数就是
GetStackFrames_generic; GetStackFramesWithContext_genric;
获得这四个函数后,” stacktrace_impl_setup-inl.h”头文件中有如下语句
所以在这里相当于完成了impl_generic的定义
4.3调用栈信息是如何获取的
在上面的宏的定义中,调用了backtrace函数,