使用Visual Studio 2013在C中查找内存泄漏
我正在使用Visual Studio 2013,正在学习C编程课程,我们开始讨论内存错误,特别是内存泄漏,以及如何在Linux上使用Valgrind检测它们 我想知道是否有一种方法可以使用VS2013检测此类内存泄漏。我尝试在线搜索,但它只会导致大量文章和博客以及msdn帖子和博客,其中包含大量单词,如转储文件、分析文件等,这很奇怪,因为: 它听起来如此复杂、复杂和不直观,实际上很难理解 2这很奇怪的主要原因是VS是最先进的IDE,微软在这方面花了很多钱,但据我所知,似乎没有简单的方法可以使用VS来检测内存泄漏-当然没有像Valgrind这样简单的方法,我只需要编译程序并运行命令 valgrind-泄漏检查=是程序名 它简单地向我打印出它认为内存泄漏的所有位置,并描述了错误,比如在分配malloc后没有释放内存,因此在程序完成后有死内存,或者访问超出数组边界的内存使用Visual Studio 2013在C中查找内存泄漏,c,memory,visual-studio-2013,memory-leaks,memory-profiling,C,Memory,Visual Studio 2013,Memory Leaks,Memory Profiling,我正在使用Visual Studio 2013,正在学习C编程课程,我们开始讨论内存错误,特别是内存泄漏,以及如何在Linux上使用Valgrind检测它们 我想知道是否有一种方法可以使用VS2013检测此类内存泄漏。我尝试在线搜索,但它只会导致大量文章和博客以及msdn帖子和博客,其中包含大量单词,如转储文件、分析文件等,这很奇怪,因为: 它听起来如此复杂、复杂和不直观,实际上很难理解 2这很奇怪的主要原因是VS是最先进的IDE,微软在这方面花了很多钱,但据我所知,似乎没有简单的方法可以使用V
因此,我的问题是如何使用VS 2013,以获得相同的结果,并首先在高层发现程序中是否存在内存泄漏,第二,以一种简单的方式检测这些泄漏的位置-最好不涉及转储文件,因为我不知道如何在VS中使用它们。我提供的答案不可能是完美的,因为我详尽地解释了VS2013等的所有功能。提供了寻找C/C++堆hickups可能是一本畅销书。就这一点而言,它不是很薄 首先,我将不介绍的内容: h-语义注释,如果提供,也可由MS工具使用。 并非所有的Crt*功能都可用。只有少数人提出了这个想法。 应用程序设计人员可能需要向其设计中添加的其他步骤,以实现生产质量代码库。 话虽如此,这里有一段带注释的代码,其中包含各种各样的bug,期待着一场反对票的狂欢,因为这就是上次我故意展示bug代码时发生的事情。。。。每个bug都附有注释,说明如何通过VS2013提供的功能检测到它。在运行时、编译时或静态代码分析时 编译时错误部分放在注释中,顺便说一句
#include "stdafx.h"
#include <crtdbg.h>
#include <malloc.h>
#include <cstdint>
#include <cstdlib>
// This small helper class shows the _Crt functions (some of them)
// and keeps the other code less cluttered.
// Note: This is NOT what you should do in production code,
// as all those _Crt functions disappear in a release build,
// but this class does not disappear...
class HeapNeutralSection
{
_CrtMemState m_start;
public:
HeapNeutralSection()
{
_CrtMemCheckpoint(&m_start);
}
~HeapNeutralSection()
{
_CrtMemState now;
_CrtMemState delta;
_CrtMemCheckpoint(&now);
if (_CrtMemDifference(&delta, &m_start, &now))
{
// This code section is not heap neutral!
_CrtMemDumpStatistics(&delta);
_CrtDumpMemoryLeaks();
_ASSERTE(false);
}
}
};
static void DoubleAllocationBug()
{
{
HeapNeutralSection hns;
uint32_t *rogue = (uint32_t*)malloc(sizeof(uint32_t));
if (NULL != rogue)
{
*rogue = 42; // Static Analysis without the NULL check: Dereferencing null pointer.
}
rogue = (uint32_t*)malloc(sizeof(uint32_t));
free(rogue);
// detected in destructor of HeapNeutralSection.
}
}
static void UninitializedPointerAccessBug()
{
// uint32_t *rogue;
// *rogue = 42; // C4700: uninitialized local variable 'rogue' used.
}
static void LeakBug()
{
{
HeapNeutralSection hns;
uint32_t *rogue = (uint32_t*)malloc(sizeof(uint32_t));
if (NULL != rogue)
{
*rogue = 42; // Static Analysis without the NULL check: Dereferencing null pointer.
}
}
}
static void InvalidPointerBug()
{
// Not sure if the C-compiler also finds this... one more reason to program C with C++ compiler ;)
// uint32_t *rogue = 234; // C2440: 'initalizing': cannot convert from 'int' to 'uint32_t *'
}
static void WriteOutOfRangeBug()
{
{
HeapNeutralSection hns;
uint32_t * rogue = (uint32_t*)malloc(sizeof(uint32_t));
if (NULL != rogue)
{
rogue[1] = 42; // Static analysis: warning C6200: Index '1' is out of valid index range '0' to '0' for non-stack buffer 'rogue'.
rogue[2] = 43; // Static analysis: warning C6200: Index '2' is out of valid index range '0' to '0' for non-stack buffer 'rogue'.
// warning C6386: Buffer overrun while writing to 'rogue': the writable size is '4' bytes, but '8' bytes might be written.
}
free(rogue); // We corrupted heap before. Next malloc/free should trigger a report.
/*
HEAP[ListAppend.exe]: Heap block at 0076CF20 modified at 0076CF50 past requested size of 28
ListAppend.exe has triggered a breakpoint.
*/
}
}
static void AccessAlreadyFreedMemoryBug()
{
{
HeapNeutralSection hns;
uint32_t * rogue = (uint32_t*)malloc(sizeof(uint32_t));
free(rogue);
*rogue = 42; // Static analysis: warning C6001: Using uninitialized memory 'rogue'.
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// checks heap integrity each time a heap allocation is caused. Slow but useful.
_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF);
AccessAlreadyFreedMemoryBug();
WriteOutOfRangeBug();
UninitializedPointerAccessBug();
DoubleAllocationBug();
// _CrtDumpMemoryLeaks();
return 0;
}
最后同样重要的是,在Windows CE和DDK中,可能在平台SDK中,曾经有两个静态代码检查器prefast和prefix。但也许它们现在已经过时了。
此外,还有一些MS研究项目,超越了sal.h,例如:
,这有助于发现并发错误等。实际上,根据计算方式,可以检测内存泄漏的级别分为2级或3级。首先,即使使用免费社区版,也可以使用VS2013内置的静态代码分析器。第二,您可以进行调试构建并使用运行时检查,以使您受益。最后,windows API中有一组函数,允许检查堆并找出是否存在损坏的堆、悬空堆对象等。。。也许你最好的防泄漏武器是切换到C++,而不是直接使用直接内存分配来编写代码。使用第三方工具:VLD、DeleKek等等。实际上,这些工具与正常堆诊断功能一样,将结果封装在一个糖果UI中。为什么要使用工具来替换6-10行插装代码?@user2225104我有几件事想让你澄清一下/eleborate关于你的第一条评论请记住,我到目前为止还没有做过内存分析,所以我不熟悉这些工具:1 VS中的静态代码分析器是什么,如何使用它在UI中的位置和它是做什么的?例如,它能表明我有悬挂的物体吗?2使用运行时检查是什么意思-您是指一步一步地运行代码吗?无法定位内存泄漏3您在谈论什么函数和API,更实际的是-我如何使用它们,在哪里使用它们?