【问题标题】:Finding memory leaks in a C++ application with Visual Studio使用 Visual Studio 在 C++ 应用程序中查找内存泄漏
【发布时间】:2011-06-15 00:04:44
【问题描述】:

在 Linux 中,我一直使用 valgrind 来检查应用程序中是否存在内存泄漏。 Windows 中的等价物是什么?这可以用 Visual Studio 2010 完成吗?

【问题讨论】:

标签: c++ visual-studio visual-studio-2010 memory-leaks valgrind


【解决方案1】:

您可以使用 DevPartner 工具在 Visual Studio 中查找 C++ 应用程序中的内存泄漏。

【讨论】:

    【解决方案2】:

    Visual Leak Detector 怎么样?它不是内置的,但我认为它是最受欢迎的。

    【讨论】:

    【解决方案3】:

    C++ Memory Validator 在使用 Visual Studio、Delphi 和其他编译器构建的本机 Windows 程序中查找内存并处理泄漏。速度快,可以处理大型工作负载(一些用户一次跟踪数十亿次分配和解除分配)。

    披露:我是 C++ Memory Validator 的设计者。我们构建它是因为当我们与 SolidWorks R&D Ltd 合作时,其他工具无法处理工作量。

    【讨论】:

      【解决方案4】:

      Visual Studio 2015 及更高版本具有本机内存泄漏诊断工具,详情请查看:https://dzone.com/articles/native-memory-leak-diagnostics

      【讨论】:

      • 社区版是否也提供此功能?
      • 在我的 VS 2017 社区版中可以使用,不确定 2015 年。
      【解决方案5】:

      Dr. Memory 是一个内存监控工具,能够识别内存相关的编程错误,例如访问未初始化的内存、访问不可寻址的内存(包括分配的堆单元之外和堆下溢和溢出)、访问已释放的内存、双释放、内存泄漏和(在 Windows 上)处理泄漏、GDI API 使用错误以及对未保留线程本地存储槽的访问。

      博士。内存可在未修改的应用程序二进制文件上运行,该二进制文件在商用 IA-32、AMD64 和 ARM 硬件上运行在 Windows、Linux、Mac 或 Android 上。

      博士。内存建立在DynamoRIO动态检测工具平台之上。

      【讨论】:

      • 按照页面上的说明,我得到“Dr.Memory internal crash”有什么建议吗?
      • DrM 在工作时非常棒,但就像其他人发现的那样,2020 年 2 月的 2.3.0.1 容易出现内部段错误。
      【解决方案6】:

      Application Verifier 是检测本机(C 或 C++)应用程序泄漏的好工具。您可以将它与 Visual Studio 或 WinDbg 一起使用。除了内存泄漏,您还可以检查堆损坏、无效句柄使用情况。将应用程序验证程序与 WinDbg (!analyze -v) 一起使用可以提供很好的洞察力。

      【讨论】:

        【解决方案7】:

        Visual Studio 2019 有一个不错的内存分析工具,它可以在调试时以交互方式使用,也可以通过编程(无需调试)来使用,下面我将在这两种情况下展示一个最小的示例。

        主要思想是在进程开始和结束时对堆进行快照,然后比较内存的状态以检测潜在的内存泄漏。

        交互式

        创建以下main.cpp 文件(在新的控制台应用程序中):

        #include <string.h>
        int main()
        {
         int a = 1;
         char* s = new char[17];
         strcpy_s(s,17,"stackoverflow_pb");
         char* ss = new char[14];
         strcpy_s(ss, 14,"stackoverflow");
         delete[] ss;
         return 0;
        }
        

        然后:

        1. 在第一行“int a...”放置断点
        2. 单击调试 > 窗口 > 显示诊断工具;并选择内存使用情况
        3. 然后调试代码(F5),当断点命中时,点击内存使用摘要工具栏上的Take snapshot
        4. 转到最后一行“return 0..”(step over (F10) 几次)并拍摄另一个快照。
        5. 点击第二个快照中的红色箭头(在内存使用选项卡中)
        6. 这将打开一个新的“快照”选项卡,允许您将此快照与第一个(或另一个)快照进行比较并检测内存泄漏。在此示例中,变量 s (stackoverflow_pb) 存在内存泄漏。您可以通过双击“char[]”对象找到它。

        上述过程的关键步骤如下图所示:

        通过编程

        将代码替换为以下内容:

        #include <iostream>
        
        #include "windows.h"
        #define _CRTDBG_MAP_ALLOC //to get more details
        #include <stdlib.h>  
        #include <crtdbg.h>   //for malloc and free
        int main()
        {
            _CrtMemState sOld;
            _CrtMemState sNew;
            _CrtMemState sDiff;
            _CrtMemCheckpoint(&sOld); //take a snapshot
            char* s = new char[17];
            strcpy_s(s, 17, "stackoverflow_pb");
            char* ss = new char[14];
            strcpy_s(ss, 14, "stackoverflow");
            delete[] ss;
            _CrtMemCheckpoint(&sNew); //take a snapshot 
            if (_CrtMemDifference(&sDiff, &sOld, &sNew)) // if there is a difference
            {
                OutputDebugString(L"-----------_CrtMemDumpStatistics ---------");
                _CrtMemDumpStatistics(&sDiff);
                OutputDebugString(L"-----------_CrtMemDumpAllObjectsSince ---------");
                _CrtMemDumpAllObjectsSince(&sOld);
                OutputDebugString(L"-----------_CrtDumpMemoryLeaks ---------");
                _CrtDumpMemoryLeaks();
            }
            return 0;
        }
        

        它做同样的事情,但通过代码,所以你可以将它集成到一个自动构建系统中,函数_CrtMemCheckpoint 拍摄快照,_CrtMemDifference 比较快照的内存状态,如果它们不同,则返回 true。

        既然是这种情况,它就会进入条件块并通过几个函数打印有关泄漏的详细信息(请参阅_CrtMemDumpStatistics_CrtMemDumpAllObjectsSince_CrtDumpMemoryLeaks - 后者不需要快照)。

        要查看输出,请在最后一行“return 0”中放置一个断点,点击F5 并查看调试控制台。这是输出:


        要了解更多信息,请参阅以下链接:

        【讨论】:

        • 这很好。有没有办法我们可以检查 1. 混合数组 new[] 和错误的 delete,2. 访问已释放的内存,3. 其他破坏内存的方式,如越界访问等。 4.访问未初始化的内存
        • 对不起,我不知道 1,3 和 4,但我会使用静态分析工具。关于 2(访问释放的内存),您可以使用 _CRTDBG_DELAY_FREE_MEM_DF 标志(参见上面的链接“CRT 调试堆文件”)。
        • 谢谢。 OutputDebugStringW 需要 LPCWSTR,(3 个字符不足以进行编辑,因为其余的答案是完美的!)
        • /fsanitize=address 现在可以与 x64 和 x86 一起使用,以解决类似的内存问题。 AddressSanitizer
        【解决方案8】:

        用于跟踪本机 (C++) 内存泄漏的独立工具 (CLI)。在发布模式下运行您的应用程序(PDB 应该可用)并让它一起运行。它会输出所有可疑的调用堆栈及其相关的泄漏大小:

        GitHub: C++ Memory Leak Detector for Windows

        【讨论】:

          【解决方案9】:

          一个可靠的解决方案是将Address Sanitizer 用于Visual Studio。这是一个跨平台/跨编译器解决方案,因此您获得的知识将转移到gcc and clang

          此工具具有线程清理和一般内存错误检测(释放后使用、双重释放、未初始化使用等)的扩展,但泄漏检测是它的强项之一。您需要 Microsoft 编译器的 /fsanitize=address /Zi 选项,但您可以参考第一篇链接文章,了解如何将其合并到解决方案和更大的项目中(通过 CMake 配置或项目属性调整)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-05-12
            • 1970-01-01
            • 1970-01-01
            • 2014-06-26
            • 2014-01-02
            • 1970-01-01
            • 1970-01-01
            • 2012-06-24
            相关资源
            最近更新 更多