Linux下c++程序内存泄漏检测代码范例

本文介绍了在Linux环境下,针对C++程序内存泄漏的检测方法,特别是通过自定义轻量级检测代码来避免valgrind带来的资源开销和效率影响。提倡使用共享指针以自动管理内存,减少内存泄漏问题。
摘要由CSDN通过智能技术生成

Linux下对于程序内存泄漏检测的方法很多,最常用的的莫过于使用valgrind工具。但是valgrind相当于让程序在虚拟机中运行,会带来较大的系统资源开销,还会对程序的运行效率产生较大影响,对于那种资源占用大的程序,如果需要长时间运行才能暴露的泄漏问题,它就显得不太好用。

linux下的c++程序中自己实现一个轻量级的泄漏检测代码其实是比较方便的,下面我就给出一个简单的范例,并作简单的说明。当然,我们还是应该提倡使用共享指针,用共享指针自动管理内存可以避免内存泄漏这样的不必要的麻烦。

 

 

基本原理:
1.利用glibc提供的__malloc_hook, __free_hook系列函数对内存分配释放做监控;(详见glibc的官方文档)
2.利用backtrace函数获取函数调用栈,并记录;
3.利用backtrace_symbols对调用栈对应的函数做解析;
进一步处理:
4.使用abi::__cxa_demangle把函数名解析为源代码风格;
5.使用addr2line解析出函数调用栈对应的代码行;
6.对于动态库(.so)中的地址解析,需要先在/proc/<pid>/maps文件中找到动态库映射的基地址,才能做解析。
注意:
编译连接参数中使用-g -rdynamic
 
以上每步具体实现的代码可能都没有达到最优,甚至可能是笨办法,如果有更好的实现方案请直接替换,也欢迎赐教。

示例代码:
leakmom.cpp

/* Prototypes for __malloc_hook, __free_hook */
#include   <malloc.h>
#include   <map>
#include   <utility>
#include   <execinfo.h>
#include   <errno.h>
#include     <assert.h>
#include   <cxxabi.h>
#include   <sys/types.h>
#include   <unistd.h>
#include   <stdlib.h>
#include   "leakmon.h"

CMutexLock   gLock   ;
std :: map   < void *,   _PtrInfo >   gPtrInfo   ;
std :: map   < const   LmCallStack *,   _AllocInfo     __comp >   gLeakInfo ;


const   int   LmCallStack ::   MAX_STACK_LAYERS   = 32;

/* Prototypes for our hooks. */
static   void   my_init_hook   (   void );
static   void   * my_malloc_hook   (   size_t ,   const   void   *);
static   void   my_free_hook   (   void *,   const   void   *);

void   *(* __MALLOC_HOOK_VOLATILE   old_malloc_hook )(   size_t   __size   ,   const   void   *) ;
void   (* __MALLOC_HOOK_VOLATILE   old_free_hook ) (   void   * __ptr   ,   const   void   *);
/* Override initializing hook from the C library. */
void   (* __MALLOC_HOOK_VOLATILE   __malloc_initialize_hook ) (   void ) =   my_init_hook ;

void   my_init_hook   ( void )
{
      old_malloc_hook   =   __malloc_hook   ;
      old_free_hook   =   __free_hook   ;
      __malloc_hook   =   my_malloc_hook   ;
      __free_hook   =   my_free_hook   ;
}

static   void   * my_malloc_hook   (   size_t   size   ,   const   void   * caller   )
{
      void   * result   ;
         gLock . lock   ();
      /* Restore all old hooks */
      __malloc_hook   =   old_malloc_hook   ;
      __free_hook   =   old_free_hook   ;
      /* Call recursively */
      result   =   malloc   ( size );
      /* Save underlying hooks */
      old_malloc_hook   =   __malloc_hook   ;
      old_free_hook   =   __free_hook   ;
      /* printf might call malloc, so protect it too. */
      //printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
         RecordPtr (   result   ,   size );

      /* Restore our own hooks */
      __malloc_hook   =   my_malloc_hook   ;
      __free_hook   =   my_free_hook   ;
         gLock . unlock   ();
      return   result   ;
}

static   void   my_free_hook   (   void   * ptr   ,   const   void   * caller   )
{
         gLock . lock   ();
      /* Restore all old hooks */
      __malloc_hook   =   old_malloc_hook   ;
      __free_hook   =   old_free_hook   ;
      /* Call recursively */
      free   ( ptr   );
      /* Save underlying hooks */
      old_malloc_hook   =   __malloc_hook   ;
      old_free_hook   =   __free_hook   ;
      /* printf might call free, so protect it too. */
      //printf ("freed pointer %p\n", ptr);

         RemovePtr (   ptr   );

      /* Restore our own hooks */
      __malloc_hook   =   my_malloc_hook   ;
      __free_hook   =   my_free_hook   ;
         gLock . unlock   ();
}

void   RecordPtr   (   void *   ptr ,   size_t   size )
{
         //   获取调用栈
         void   * array   [ LmCallStack ::   MAX_STACK_LAYERS ];
         int   cstSize   =   backtrace (   array
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值