首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用Visual 2013在C中查找内存泄漏

用Visual 2013在C中查找内存泄漏
EN

Stack Overflow用户
提问于 2015-04-16 23:31:00
回答 1查看 1.4K关注 0票数 1

我正在使用Visual 2013,并上了C编程课程,我们开始讨论内存错误的分离,特别是内存泄漏,以及如何在Linux上使用Val差伦来检测它们。

我想知道是否有办法使用VS 2013来检测这样的内存泄漏。我试着在网上搜索,但它只会导致大量文章、博客、msdn帖子和博客,其中包含了大量的单词,比如转储文件,并对它们进行分析,等等,这很奇怪,因为:

( 1)它听起来如此复杂、复杂和不直观,实际上是难以理解的。

2)之所以这么奇怪,主要是因为VS是当今最先进的IDE,微软在这方面花费了这么多钱,但据我所读到,似乎没有简单的方法来使用VS来检测内存泄漏--当然,这不可能像Val差尔那样简单,我只需要编译程序并运行命令。

气功-泄漏-检查=是的ProgramName

它只是将它认为存在内存泄漏的所有位置打印给我,并描述了错误(比如在使用malloc分配内存之后没有释放内存,因此在程序完成后有“死”内存,或者访问超出数组界限的内存)。

因此,我的问题是如何使用VS 2013,以获得相同的结果,并首先在高级程序中发现内存泄漏,其次--以简单的方式检测这些泄漏的位置--最好不涉及转储文件(我不知道如何在VS中使用它们)。

EN

回答 1

Stack Overflow用户

发布于 2015-04-18 01:14:07

我所提供的答案不可能像详尽地解释所有特性、VS2013等,提供找到C/C++堆hickup的建议,这可能是一本很畅销的书。在这件事上不是很薄的一个。

首先,我将不涉及的事情:

  • sal.h -语义注释(如果提供的话,MS工具也会使用这些注释)。
  • 并不是所有的_Crt*函数都可用。只有少数人能给出这个想法。
  • 应用程序设计器可能会为“生产质量”代码库在其设计中添加其他步骤。

话虽如此,这里有一段包含各种bug的带注释的代码。每个bug都有注释,说明如何通过VS2013提供的工具来检测它。在运行时、编译时或使用静态代码分析。

编译时错误部分放在注释中,顺便说一句。

代码语言:javascript
运行
复制
#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和DDK(也可能是在平台SDK中)中,曾经有两个静态代码检查器“预快”和“前缀”。但也许它们现在已经过时了。

此外,还有一些MS研究项目,它们超越了sal.h,例如:VCC,它帮助查找并发错误等等。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29687712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档