由于项目原因,需要定位一个内存泄露问题,由于我们的系统是运行在VxWorks下的,而网上大多数开源的内存工具都是在linux下,因此需要自己想些办法。
在看libgds代码时,发现了它里面一个简单的内存管理库,使用恰当时,可以帮助开发人员方便的检测内存泄露问题。
Libgds的原理就是对系统的malloc进行了替换,将malloc申请的地址、地址大小、代码行数、甚至是malloc的调用栈(如下图所示),统一记录在一个链表上面。这样,当系统运行一段时间后,查看链表中没有释放的内存,如果某一块相同特征的内存再链表上出现很多,那么很可能就是内存泄露了。
libgds对malloc的替换非常简单,仅仅是进行了宏定义的替换
#define MALLOC(s) memalloc(s,__FILE__, __LINE__)
Memalloc函数如下,编译时如果打开了HAVE_MEMORY_DEBUG宏,则会进行内存管理,否则和正常的malloc一样。
void * memalloc(size_t size, char* pcFileName, int iLineNumber)
{
void * pNewPtr = malloc(size);
#ifdef HAVE_MEMORY_DEBUG
SMemAlloc * pAlloc = NULL;
#endif
if (dAllocCount < 0) {
fprintf(stderr, "memalloc: dtor function _memory_init has not yet");
fprintf(stderr, "been called. Check the linking process!!!\n");
exit(EXIT_FAILURE);
}
if (pNewPtr == NULL) {
perror("memalloc: ");
exit(EXIT_FAILURE);
}
#ifdef HAVE_MEMORY_DEBUG
if ((plMemAlloc != NULL) && mem_flag_get(MEM_FLAG_TRACK_LEAK)) {
pAlloc= memory_alloc_init(pNewPtr, size,
pcFileName, iLineNumber);
if (list_add(plMemAlloc, pAlloc) == -1) {
fprintf(stderr, "allocation alreadymade\n");
exit(EXIT_FAILURE);
}
iAllocatedBytes += size;
if (iMaxAllocatedAtOneTime < iAllocatedBytes-iFreedBytes)
iMaxAllocatedAtOneTime=iAllocatedBytes-iFreedBytes;
}
#endif
dAllocCount++;
return pNewPtr;
}
对于一个小工程或者是新开发的工程,用libgds这种方法管理和检测内存比较方便,但是对一个大工程来说,将malloc统一替换成MALLOC不是非常现实,还需要用其他的方法。比如将libgds编译成一个lib,由这个lib统一提供malloc函数,编译时指定链接该lib,不使用libc的malloc,能很好的解决上面提到的麻烦。
当然了,内存检测是有开销的,只能在DEBUG版本中打开内存调试,RELEASE版本中,需要关闭内存调试的宏。