在未经管理的C/C++代码中,如何检测内存泄漏并避免编码指导方针?(好像这很简单 ;))
我们过去使用了一种有点傻的方法:对每个内存分配调用进行计数增加,并在释放时进行减少。在程序结束时,计数值应该为零。
我知道这不是一个好的方式,还有一些陷阱。(例如,如果您释放由平台API调用分配的内存,则您的分配计数将不完全匹配您的释放计数。当然,在调用分配内存的API调用时,我们会增加计数。)
我期待您的经验、建议和可能一些简化此过程的工具的参考。
在未经管理的C/C++代码中,如何检测内存泄漏并避免编码指导方针?(好像这很简单 ;))
我们过去使用了一种有点傻的方法:对每个内存分配调用进行计数增加,并在释放时进行减少。在程序结束时,计数值应该为零。
我知道这不是一个好的方式,还有一些陷阱。(例如,如果您释放由平台API调用分配的内存,则您的分配计数将不完全匹配您的释放计数。当然,在调用分配内存的API调用时,我们会增加计数。)
我期待您的经验、建议和可能一些简化此过程的工具的参考。
如果您正在使用Visual Studio,Microsoft提供了一些有用的函数来检测和调试内存泄漏。
我建议从这篇文章开始: https://msdn.microsoft.com/zh-cn/library/x98tx3cf(v=vs.140).aspx
以下是这些文章的简要概述。首先,需要包含这些头文件:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
当你的程序退出时,你需要调用这个函数:
Then you need to call this when your program exits:
_CrtDumpMemoryLeaks();
如果您的程序每次退出的位置不同,您可以在程序开头调用以下方法:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
现在当程序退出时,所有未被释放的分配将与它们被分配的文件和分配发生位置一起打印在“输出窗口”中。
这种策略适用于大多数程序。然而,在某些情况下,使用第三方库在启动时进行初始化可能会导致其他对象出现在内存转储中,并且可能使跟踪泄漏变得困难或不可能。另外,如果您的任何类具有与任何内存分配例程(如malloc)相同名称的成员,则CRT调试宏将会引起问题。
MSDN链接中提到的还有其他可用的技术。
std::unique_ptr
, std::shared_ptr
, std::weak_ptr
是你的好帮手。我已经使用DevStudio很多年了,但总是惊讶于有多少程序员不知道在调试运行时库中可用的内存分析工具。以下是一些入门链接:
跟踪堆分配请求 - 特别是关于唯一分配请求号的部分
当然,如果你不使用 DevStudio,则这些可能没有什么帮助。
我很惊讶没有人提到适用于Windows操作系统的DebugDiag。
它可以在发布版本上运行,甚至可以在客户现场使用。
(您只需要保留发布版本的PDB文件,并配置DebugDiag使用Microsoft公共符号服务器)
Visual Leak Detector是一个非常好的工具,尽管它不支持VC9运行时的调用(例如MSVCR90D.DLL)。
Microsoft VC++在调试模式下会显示内存泄漏,但不会显示泄漏的位置。
如果您正在使用C ++,则始终可以避免显式使用new:您可以使用vector
、string
、auto_ptr
(C++11之前的版本;在C++11中由unique_ptr
替代)、unique_ptr
(C++11)和shared_ptr
(C++11)。
当无法避免使用new时,请尝试将其隐藏在构造函数中(并在析构函数中隐藏delete);对于第三方API也是同样适用。
InitAllocCheck(ACOutput_XML)
DeInitAllocCheck()
存在着各种可替换的“malloc”库,它们允许您在结束时调用一个函数,并告诉您所有未释放的内存以及很多情况下是谁首先使用了 malloc(或 new)。