当前位置:   article > 正文

Linux下c++程序内存泄漏检测代码范例_linux c语言中使用cxxabi.h

linux c语言中使用cxxabi.h

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
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/65269
推荐阅读
相关标签
  

闽ICP备14008679号