替代系统malloc/new--选择合适的内存跟踪方案

替代系统自带的malloc/new原因无非两个: 

reason 1. 做内存profile或查找问题   

reason 2. 自定义的分配方案提高性能

 

不过文章[1]中说明了,替代全局new不是一个好做法. 其实要达到以上两点目的,笔者认为用valgrind工具链就可以了。

 

解决方案:

1. 用valgrind和massif

     valgrind的memcheck做内存泄露和bug的查找, 里面的massif工具包做内存性能profile, 足矣。比自己山寨的一个profiler要好。

     注意:tcmalloc目前还不能很好支持valgrind,  实测中jemalloc可以

 

2.  linux下C的程序可以用wrap的方式(相当于python的decorator)

     编译加上选项:gcc -Wl,-wrap,malloc

     可以做到对malloc这个函数,linker会调用__wrap_malloc代替之, 若要调用原来的malloc函数__real_malloc

     缺点:依赖于编译器支持; 对c++的new不起作用 --> 不实用

     启示:这个方法作为function装饰器,对于调试别的问题倒有帮助。(例如不改变函数的情况下,wrap一层,输出些调试信息)

3. 用__malloc_hook

    参考: http://linux.die.net/man/3/__malloc_hook

     #include <malloc.h>

     void *(*__malloc_hook)(size_t size, const void *caller);
     缺点:依赖GNU编译工具链;  容易死循环(想利用原有malloc,要参考例子中,把原__malloc_hook变量保存起来使用,并恢复现场)


4. LD_PRELOAD注入.so ,替代原

     环境变量LD_PRELOAD指定程序运行时优先加载的动态连接库,这个动态链接库中的符号优先级是最高的。标准C的各种函数都是存放在libc.so.6的文件中,在程序运行时自动链接。使用LD_PRELOAD后,自己编写的malloc的加载顺序高于glibc中的malloc,这样就实现了替换。用法 LD_PRELOAD=" ./mymalloc.so"

      缺点:在生产环境不现实。因为LD_PRELOAD相当于库注入,有安全性问题,是必须禁止的。(生产环境很多时候用-static连接)

5. 用宏或另外的函数替代new/malloc

   比如定义一个宏或者指定的函数,规定所有的分配释放都调用他。这样相当于给项目引入了额外的代码规则(而且是一立项就要遵循这个规则,否则该方法无效),不能很自然的new/delete, 如果分配和释放调用得不一致,会产生问题的。某产品组就是用宏,然后加上__FILE__, __LINE__之类的信息。

 有时候valgrind的效率是个问题(尤其生产环境),这种方案有其价值所在, 就是代码看上去比较ugly罢了

 

   用宏的例子:

   #define _New(Type, Catergory)                    (Type*)MyMemController::New((new Type), #Type, 1, sizeof(Type),   Catergory, __FILE__, __LINE__, false)

   #define _NewArray(Type, N, Catergory)          (Type*)MyMemController::New((new Type[N]), #Type, N, sizeof(Type)*(N), Catergory, __FILE__, __LINE__, true)


   

MALLOC的替代品:

     自己写一个malloc其实很复杂,要考虑线程安全等各种问题,性能到头来可能更差。google 的tcmalloc,  facebook使用的jemalloc.   多线程下性能较好,可以考虑使用。

     缺点:笔者尝试过。tcmalloc不能正确用valgrind,只能用自带gperftools(运行中会core)

                 jemalloc可以使用valgrind,不过还没完全验证是否都准确。

tcmalloc相关:

    在64位系统上要装libunwind, 对x86-64架构使用还有些问题
 

源码包的INSTALL文档里面也提到了这个问题。
 CAUTION: if you install libunwind from the url above, be aware that
   you may have trouble if you try to statically link your binary with
   perftools: that is, if you link with 'gcc -static -lgcc_eh ...'.
   This is because both libunwind and libgcc implement the same C++
   exception handling APIs, but they implement them differently on
   some platforms.  This is not likely to be a problem on ia64, but
   may be on x86-64.

主要是64位机frame-pointer的影响, 他的profile工具里的backtrace用libunwind这个库,这个库又有版本问题,各种囧啊....

笔者试过系统x86-64, freebsd,用静态链接。实际用了一下,问题很多很折腾,等他fix了再说吧.
 

windows下可以参考:

http://www.cppblog.com/feixuwu/archive/2010/07/10/119980.aspx



jemalloc暂时未发现有什么兼容性问题,运行得挺好的。

 

Reference
[1] <不要重载全局operator new>

[2] effective c++条款50:了解new和delete的合理替换时机

[3] 游戏引擎中的内存分配策略
[4] 更好的内存管理jemalloc
[5] tcmalloc官网(gperftools)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值