检查内存泄漏

 

检查内存泄漏

来源 https://www.zhihu.com/question/63946754/answer/214762551

 

linux+gcc用valgrind,windows+msvc用vs调试功能。
如果是在windows上跑mingw就坑爹了,要么买专门的商业检测软件,要么用代码侵入的方式,重载operator new,接入内存泄漏检测代码

 

只要每一个cpp在展开后都能看见这几行():

#ifdef VCZH_CHECK_MEMORY_LEAKS
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define VCZH_CHECK_MEMORY_LEAKS_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new VCZH_CHECK_MEMORY_LEAKS_NEW
#endif

在程序退出的时候,调用_CrtDumpMemoryLeaks函数,Visual Studio的output窗口就会打印所有没有释放的东西(包括全局变量——所以不要在全局变量里面使用非指针或数字类型),双击可以跳进代码。

我都配置成debug模式会检查,每次运行的时候都在检查,有时候我都忘记他在检查了然后突然就蹦出来了消息说我内存泄漏了,然后马上改。所以我的程序绝对没有内存泄漏(逃

如果是Windows的话可以利用在DEBUG环境下检查

#ifdef _WIN32
    #include <crtdbg.h>
    #ifdef _DEBUG

    #define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
    #endif
#endif

#ifdef _WIN32
	_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_LEAK_CHECK_DF);
#endif
 
除非自己实现一个GC。内存泄漏的本质是分配了内存,没有释放,而且将来也不会再使用了。上面回答说重载new, malloc都是治标不治本的方法,即使你记录了所有已分配的未释放的内存块,如果你没有办法判断将来这块内存是否会再被使用的话,你敢随便释放吗?如果你能判断出将来一定不会使用了,那么等于你实现了一个GC。要解决这个问题只能从代码编写的规范来考虑,内存的分配和释放控制在同一个scope里面,尽量避免在一个函数里面分配内存,再在另一个函数里面去释放。如果确实需要分配一块内存作为运行时全局使用,可以考虑设置initialize和destroy方法分别在work flow开始和结束的时候调用。
 
gcc的asan
好像4.8以上的gcc自带asan.
加编译选项和链接asan库就行,进程退出的时候,帮你打印出来所有申请未释放的内存

因为是一个新特性,它被安排在dev分支(Qt 5.2)。但是您可以把它cherry-pick到Qt 5.0。然后您在配置Qt时使用-address-sanitizer,为您的程序执行qmake CONFIG+=address_sanitizer。

如果您不想cherry-pick,您也可以手动为qmake设置命令行参数MAKE_CXXFLAGS、QMAKE_CFLAGS和QMAKE_LFLAGS:

$ qmake QMAKE_CXXFLAGS+="-fsanitize=address -fno-omit-frame-pointer" \
QMAKE_CFLAGS+="-fsanitize=address -fno-omit-frame-pointer" \
QMAKE_LFLAGS+="-fsanitize=address"

要启用例如地址清理器,您必须编写:

CONFIG += sanitizer sanitize_address

消毒剂选项在Qt的mkspecs(mkspecs/features/sanitizer.prfmkspecs/common/sanitize.conf中定义,当您添加时会加载它CONFIG += sanitizer快速浏览我的sanitizer.prf(Qt 5.7.0),可以看到特定的消毒剂是:

  • sanitize_address
  • sanitize_memory
  • sanitize_thread
  • sanitize_undefined
 
 
如果是Windows,考虑下Visual Leak Detector,这个对泄露点信息定位相当不错;如果是Linux,考虑下Valgrind,检测内存使用以及线程方面的Bug功能非常强大。
 
 
使用工具只能查出因为自己代码造成的内存泄漏,对于因为错误调用系统API造成的内存泄漏还是只能通过查log和review代码来定位,没办法。
 
 
============= End
 
 

 

posted @ 2020-05-07 09:00  lsgxeva  阅读(867)  评论(0编辑  收藏  举报