求助一个利用malloc_hook 定位内存泄露的问题

听海潮2012 2012-08-24 03:29:59
程序在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;
}
}


................
................
}

...全文
425 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
mujiok2003 2012-08-24
  • 打赏
  • 举报
回复
1. 改变hook的时候,线程不安全,确保没有问题。
2. 如果可以gdb,请单步跟踪一下。
听海潮2012 2012-08-24
  • 打赏
  • 举报
回复
ls的,valgrind好像无法挂到进程上去吧,并且程序是运行在单板上的,没有PC上的运行环境
听海潮2012 2012-08-24
  • 打赏
  • 举报
回复
ls的,valgrind好像无法挂到进程上去吧,并且程序是运行在单板上的,没有PC上的运行环境
ayw215 2012-08-24
  • 打赏
  • 举报
回复
为啥不用valgrind测试
听海潮2012 2012-08-24
  • 打赏
  • 举报
回复
木有人吗?大侠速来啊

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧