gpt4 book ai didi

c++ - 在 Visual C++ (Windows) 中检测内存泄漏

转载 作者:行者123 更新时间:2023-11-28 02:37:06 25 4
gpt4 key购买 nike

我正在 Visual Studio 2010 下处理一个大型 C++ 项目,并认为其中存在一些内存泄漏。我尝试了包含 crtdbg.h 的方法,但它没有多大帮助,因为我看不到泄漏发生的位置。定义 new 有两个陷阱:首先,它需要在每个 cpp 文件中完成,这实际上不是一个选项,其次,它会中断,例如促进。使用 new(nothrow) 或任何使用提升“has_new_operator.h”的东西都会打破这一点。 [编辑:它无法编译,因为重新定义的“new”没有重载“nothrow”或“boost magic”之类的东西](除非在所有 boost header (包括引用 boost 的 header )之后定义“new”)

最后但同样重要的是:我有单例。它们是使用单例模板的子类和静态函数变量实现的。其中之一是一个配置容器,其中一个注册设置(成对的字符串和整数,而不是存储在映射中)由于内存泄漏转储是在释放单例实例之前调用的,所以我得到了所有这些字符串的大量泄漏,并且单例本身。

有什么方法可以只显示真正的泄漏或在静态对象释放后将其转储?

哪些免费工具可以处理这种情况?

最佳答案

我使用了视觉检漏仪,结果非常好。它小巧整洁,可以在几秒钟内构建到您的项目中(假设您有一个正在运行的调试配置):

https://vld.codeplex.com/

如果设置正确(可以使用安装程序完成),那么您只需

#include <vld.h> 

在每个模块的 一个 .cpp 文件中 - 就是这样, header 将为您进行链接。你不必把它放在任何地方。该工具在内部使用 CrtDbg,因此您必须运行调试版本才能使其正常工作。

它会在每次运行后为您提供调试器或文本输出(如果使用配置文件进行配置),即使未通过调试器运行也是如此。它不是最强大的工具,但这些通常需要花费一些钱 ;)

编辑:通过在包含 header 之前定义VLD_FORCE_ENABLE,也可以在非调试配置中启用 VLD。但到那时结果可能会有所缓和。

编辑:我已尝试全新安装 VLD。请注意,对于 VS2013 编译器,必须使用 v2.4rc2 版本(或更高版本的 v2.3)。 v2.3 版只能在 VS2010 编译器之前使用。

安装后,我创建了一个新项目并设置了我的包含目录和库目录以包含相应的 VLD 文件夹。之后我用下面的代码测试了单例的memleak报告(注意这段代码没有意义,只是证明了一个观点):

#include <iostream>
#include <string>
#include <sstream>
#include <map>

// Uncomment this, if you want VLD to work in non-debug configurations
//#define VLD_FORCE_ENABLE

#include <vld.h>

class FooSingleton {
private:
std::map<std::string, std::string*>
_map;

FooSingleton() {
}

public:
static FooSingleton* getInstance(void) {
/* THIS WOULD CAUSE LEAKS TO BE DETECTED
SINCE THE DESTRUCTOR WILL NEVER BE CALLEd
AND THE MAP IS NOT CLEARED.
*/
// FooSingleton* instance = new FooSingleton;
// return instance;

static FooSingleton instance;
return &instance;
}

void addString(const std::string& val) {
_map.insert(std::make_pair(val, new std::string(val)));
}

~FooSingleton(void) {
auto it = _map.begin();
auto ite = _map.end();

for(; it != ite; ++it) {
delete it->second;
}
}
};

int main(int argc, char** argv) {
FooSingleton* fs = FooSingleton::getInstance();
for(int i = 0; i < 100; ++i) {
std::stringstream ss;
ss << i << "nth string.";
fs->addString(ss.str());
}

return 0;
}

使用此代码,VLD 不会报告任何泄漏,因为 getInstance() 中的静态自动变量将在退出时被破坏, map 中的元素将被删除。尽管如此,这必须完成,即使它是一个单例,否则将报告泄漏。但在这种情况下:

Visual Leak Detector Version 2.3 installed.
Aggregating duplicate leaks.
Outputting the report to the debugger and to D:\dev\projects\tmp\memleak\memleak\memory_leak_report.txt
No memory leaks detected. Visual Leak Detector is now exiting.

如果 getInstance() 中的代码更改为注释版本,则永远不会清除单例并报告以下泄漏(除其他外):

---------- Block 11 at 0x008E5928: 52 bytes ----------
Leak Hash: 0x973608A9 Count: 100
Call Stack:
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (36): memleak.exe!std::_Allocate<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0x15 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (187): memleak.exe!std::allocator<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0xB bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (560): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0xD bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (588): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0x8 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (756): memleak.exe!std::_Tree<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std:: + 0x17 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (33): memleak.exe!FooSingleton::addString + 0xA9 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (51): memleak.exe!main + 0x37 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): memleak.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): memleak.exe!mainCRTStartup
0x76BF919F (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x7739A22B (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x84 bytes
0x7739A201 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
Data:
C0 53 8E 00 30 67 8E 00 C0 53 8E 00 98 58 8E 00 .S..0g.. .S...X..
30 6E 74 68 20 73 74 72 69 6E 67 2E 00 CD CD CD 0nth.str ing.....
0C 00 00 00 0F 00 00 00 CD CD CD CD 48 56 8E 00 ........ ....HV..
01 00 CD CD

您可以清楚地看到此代码块的Count: 100,这是正确的。

我还编辑了安装目录中的 vld.ini 文件以启用以下设置:

AggregateDuplicates = yes
ReportTo = both

这些确保 a) 所有重复的泄漏都被压缩到一个带有泄漏计数的报告(如上所述,否则会有 100 个条目)和另一个,以便报告文件被转储到申请。

因此对于单例来说,只要您使用正在使用的静态自动变量方法并在析构函数中进行清理,它就可以正常工作。

编辑:此外,可以在特定代码段禁用检测。如果将上面的代码修改成这样:

void addString(const std::string& val) {
VLDDisable();
_map.insert(std::make_pair(val, new std::string(val)));
VLDEnable();
}

泄漏将永远不会被分析和跟踪。

关于c++ - 在 Visual C++ (Windows) 中检测内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27087361/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com