求助一个利用malloc_hook 定位内存泄露的问题
程序在linux系统上,通过top信息,发现有内存泄露的可能,但但代码量巨大,无法通过走查解决,且代码是一个进程,一般工具无法attach上进行检查,于是使用malloc_hook,自己实现了一下,但是进程起不来,有coredump,通过gdb coredump信息如下:
现在就是不明白,在my_malloc_hook,使用map是不是会有什么问题?
我自己写程序验证没有问题,但一放到产品代码上进程就起不来,coredump内容如下,请教各位大侠,谢谢!!!
(gdb) run
Starting program: /tmp/ljydir/OamAma
[Thread debugging using libthread_db enabled]
Program received signal SIGSEGV, Segmentation fault.
0x0093c6df in std::_Rb_tree_decrement(std::_Rb_tree_node_base*) () from /usr/lib/libstdc++.so.6
(gdb) bt
#0 0x0093c6df in std::_Rb_tree_decrement(std::_Rb_tree_node_base*) () from /usr/lib/libstdc++.so.6
#1 0x080cf417 in operator-- (this=0x18e4b860, __v=...)
at /com/utils/tomcase/xgcc_rhel/v05.00.00/usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/bits/stl_tree.h:197
#2 std::_Rb_tree<unsigned int, std::pair<unsigned int const, long*>, std::_Select1st<std::pair<unsigned int const, long*> >, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, long*> > >::insert_unique (
this=0x18e4b860, __v=...)
at /com/utils/tomcase/xgcc_rhel/v05.00.00/usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/bits/stl_tree.h:929
#3 0x080cc829 in insert (size=28, caller=0x761bae)
at /com/utils/tomcase/xgcc_rhel/v05.00.00/usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/bits/stl_map.h:396
#4 my_malloc_hook (size=28, caller=0x761bae) at /vob/ngn_src/srcbase/OamAma/bin/../OamAmaMain.cc:162
#5 0x007611de in malloc () from /lib/libc.so.6
#6 0x00761bae in malloc_hook_ini () from /lib/libc.so.6
#7 0x007611de in malloc () from /lib/libc.so.6
#8 0x0099aab7 in operator new(unsigned int) () from /usr/lib/libstdc++.so.6
#9 0xf76ddc2a in __static_initialization_and_destruction_0 (__initialize_p=<value optimized out>,
__priority=<value optimized out>) at /vob/ngn_src/srcbase/SysCmn/bin/../SysCmnBinaryIE.cc:46
#10 0xf76ef736 in __do_global_ctors_aux () from /Spatial/msc/active/patch/libSysCmn.so
#11 0xf76c993d in _init () from /Spatial/msc/active/patch/libSysCmn.so
#12 0x006e3ad3 in call_init () from /lib/ld-linux.so.2
#13 0x006e3be3 in _dl_init_internal () from /lib/ld-linux.so.2
#14 0x006d684f in _dl_start_user () from /lib/ld-linux.so.2
我的实现是在代码中添加了部门代码,通过或冲下malloc_hook,free_hook,使用一个MAP 对象将内存分配时的情况记录下来,free时从map中删除,最后check map中对象的个数来判断内存泄漏情况,代码如下:
#include<malloc.h>
#include<fstream>
#include<time.h>
#include<map>
#include<iterator>
// 这个个宏是用来记录内存分配时一个调用栈的
#define CSFM_FBT_DEPTH 15
#define CSFM_GEN_FBT(_fbt) \
do { \
unsigned long* __ebp = 0; \
unsigned long __eip = 0; \
int __i = 0; \
long* __p = _fbt; \
for (; __i < CSFM_FBT_DEPTH; __i++) \
{ \
if (__i == 0) \
{ \
__asm__ volatile ("movl $., %0" : "=r" (__eip)); \
*__p++ = __eip; \
continue; \
} \
else if (__i == 1) \
{ \
__asm__ volatile ("mov %%ebp, %0" \
:"=r"(__ebp)); \
} \
else \
{ \
__asm__ volatile ("mov %1, %%eax\n" \
"mov (%%eax), %0" \
:"=r"(__ebp) \
:"r"(__ebp)); \
} \
if (__ebp == 0) \
break; \
*__p++ = *(__ebp + 1); \
} \
*__p = 0; \
} while(0)
//一个全局变量map ,用来记录当未释放内存的情况,key时内存分配的地址,value是一个指针,实际上
//指向一个数组,用来存放调用栈的
std::map<unsigned int,long int*> debugMap;
// my malloc definition
/* Prototypes for our hooks. */
static void my_init_hook(void);
static void *my_malloc_hook(size_t, const void *);
static void *my_realloc_hook(void *ptr, size_t size, const void *caller);
static void my_free_hook(void *ptr,const void *);
/* Variables to save original hooks. */
static void *(*old_malloc_hook)(size_t, const void *) = 0;
static void *(*old_realloc_hook)(void *ptr, size_t size, const void *caller)=0;
static void (*old_free_hook)(void *ptr,const void*) = 0;
/* Override initialising hook from the C library. */
void (*__malloc_initialize_hook) (void) = my_init_hook;
static void my_init_hook(void)
{
old_malloc_hook = __malloc_hook;
__malloc_hook = my_malloc_hook;
old_realloc_hook = __realloc_hook;
__realloc_hook = my_realloc_hook;
old_free_hook = __free_hook;
__free_hook = my_free_hook;
}
static void my_un_hook(void)
{
__malloc_hook = old_malloc_hook;
__realloc_hook = old_realloc_hook;
__free_hook = old_free_hook;
}
// 重写malloc_hook
static void *my_malloc_hook (size_t size, const void *caller)
{
void *result=NULL;
long int *addressArr= NULL;
/* Restore all old hooks */
__malloc_hook = old_malloc_hook;
/* Call recursively */
result = malloc (size);
/* Save underlying hooks */
old_malloc_hook = __malloc_hook;
if(NULL != result)
{
addressArr = new long int[CSFM_FBT_DEPTH];
memset(addressArr,0,sizeof(long int)*CSFM_FBT_DEPTH);
CSFM_GEN_FBT(addressArr);
///////////下面这行就是coredump出来的出错的那一行代码,insert时出错
debugMap.insert(std::pair<unsigned int,long int*>((unsigned int)result,addressArr));
}
/* Restore our own hooks */
__malloc_hook = my_malloc_hook;
return result;
}
static void *my_realloc_hook(void *ptr, size_t size, const void *caller)
{
void *result=NULL;
long int *addressArr= NULL;
void *old_mem_add = ptr;
std::map<unsigned int,long int*>::iterator itor;
/* Restore all old hooks */
__realloc_hook = old_realloc_hook;
/* Call recursively */
result = realloc(ptr,size);
/* Save underlying hooks */
old_realloc_hook = __realloc_hook ;
if(NULL != result)
{
__malloc_hook = old_malloc_hook;
addressArr = new long int[CSFM_FBT_DEPTH];
old_malloc_hook = __malloc_hook;
__malloc_hook = my_malloc_hook;
memset(addressArr,0,sizeof(long int)*CSFM_FBT_DEPTH);
CSFM_GEN_FBT(addressArr);
//new alloc
itor = debugMap.begin();
itor = debugMap.find((unsigned int)old_mem_add);
if(itor!=debugMap.end())
{
__free_hook = old_free_hook;
delete []itor->second;
debugMap.erase(itor);
old_free_hook = __free_hook;
__free_hook = my_free_hook;
}
debugMap.insert(std::pair<unsigned int,long int*>((unsigned int)result,addressArr));
}
/* Restore our own hooks */
__realloc_hook = my_realloc_hook;
return result;
}
static void my_free_hook(void *ptr, const void *caller)
{
std::map<unsigned int,long int*>::iterator itor;
__free_hook=old_free_hook;
free(ptr);
itor = debugMap.begin();
itor = debugMap.find((unsigned int)ptr);
if(itor != debugMap.end())
{
delete []itor->second;
debugMap.erase(itor);
// printf ("free(%p) called from %p.\n", ptr, caller);
}
old_free_hook = __free_hook;
__free_hook = my_free_hook;
}
//check map中元素个数,并将结果写入文件
// When the programme finished,check if the memory leak occured.
void checkMemoryLeak()
{
fstream file_handler;
std::map<unsigned int,long int*>::iterator itor;
//unhook
my_un_hook();
//create log file
file_handler.open("/tmp/debugleak.log",ios::out);
if(!file_handler.rdbuf()->is_open())
{
debugMap.clear();
return;
}
file_handler<<"*******************************Memory leak check result*****************************\n";
if(true == debugMap.empty())
{
file_handler<<"Well done,no memory leak.\n";
file_handler.close();
return;
}
file_handler<<"There are "<<debugMap.size()<<" blocks mem lost.\n";
itor = debugMap.begin();
while(itor !=debugMap.end())
{
file_handler<<"Lost block address=0x"<<hex<<itor->first<<"\n";
file_handler<<"==========back trace=============\n";
for(int i = 0;i<CSFM_FBT_DEPTH;i++)
{
file_handler<<"0x"<<hex<<itor->second[i]<<"\n";
}
delete [](itor++)->second;
}
debugMap.clear();
file_handler.close();
}
// 进程的main 函数
int main(int pArgc, char *pArgv[])
{
//jinyangl add
time_t tStartTime;
time_t tCurrentTime;
time(&tStartTime);
.............
.............
.............
//jinyangl add
while (amaPtr->runFlag)
{
mpPtr->getNextMsg(mailboxWtrLvl, &primitive);
time(&tCurrentTime); // three hours
if((tCurrentTime-tStartTime)>10800)
{
checkMemoryLeak();
break;
}
}
................
................
}