【问题标题】:What tool can I use to analyze memory usage? [closed]我可以使用什么工具来分析内存使用情况? [关闭]
【发布时间】:2012-08-23 10:08:05
【问题描述】:

我有一个使用 Visual Studio 2008 使用 C++ 编写的 Windows 应用程序。我想获得有关内存使用情况的统计信息,以找到处理内存使用情况的瓶颈和位置。理想情况下,我希望有一个工具可以做到这一点,而不必进入并将计数器/分析逻辑添加到代码本身。基本上我正在寻找的是:

  • 所有分配的列表(释放与否无关紧要,每次分配时我都想知道)
  • 每个分配的调用堆栈和一个计数器,表示调用代码和分配内存的次数。
  • 有关已释放和未释放内存的信息(以查找泄漏)。理想情况下,它应该足够智能来确定内存是否仍在使用中,或者它是否真的已经泄漏(通过作用域或其他一些智能机制)。

我不在乎它是否是免费工具。以下是我已经看过的一些工具:

  • Rational PurifyPlus:老实说,我无法充分利用这个工具。它返回很多误报。此外,它并没有给出我上面列表中的前 2 项,而是似乎只关注内存错误和泄漏。
  • Sysinternals VMMap:这个工具很有趣,可以让我看到内存是如何分布的(堆栈、堆和共享堆等)。它还让我看到分配的调用树,但不是很直观或有用。很难从数据中理解。
  • DevPartner Boundschecker:我真的认为这是迄今为止最没用的工具。几年前我在他们被 DevPartner 收购之前使用了它,我记得它工作得更好。但它并没有真正为我提供我需要的统计数据,而且它似乎也无法正确检测内存泄漏。

我提前感谢任何帮助/建议。我的应用程序是一个服务器,在压力测试期间随着时间的推移会遇到严重的内存增长问题(最终由于虚拟字节超过 32 位应用程序的限制而崩溃)。拥有正确的工具将帮助我隔离我们分配内存的位置以及我们可能泄漏内存的位置。

【问题讨论】:

  • 你是否可以在 Linux 上编译你的代码,否则问题太大了?顺便说一句,如果您分配了很多自己的类,您可以使用 CRTP 来计算和记录活动实例的数量:stackoverflow.com/questions/7097679/…

标签: c++ windows memory-leaks profiling


【解决方案1】:

在我的工作地点,我们使用Software Verification's Memory Validator。它将为您提供各种内存统计信息、分配列表、每个分配的调用堆栈和内存泄漏。事实证明,它偶尔对我的工作经验很有用。

【讨论】:

    【解决方案2】:

    您能否修改您的代码以使用mallocreallocfree 的调试版本?如果是,请检查_malloc_dbg_realloc_dbg_free_dbg

    (您可以根据这些函数编写自己的newdelete 运算符。)

    #ifdef _DEBUG
    # define _CRTDBG_MAP_ALLOC 1
    # include <Crtdbg.h>
    # define malloc(size)       _malloc_dbg(size,_CLIENT_BLOCK,__FILE__,__LINE__)
    # define realloc(addr,size) _realloc_dbg(addr,size,_CLIENT_BLOCK,__FILE__,__LINE__)
    # define free(addr)         _free_dbg(addr,_CLIENT_BLOCK)
    void * operator new ( size_t size, const char * filename, int linenumber )
    {
      void * addr = _malloc_dbg( size, _CLIENT_BLOCK, filename, linenumber );
      if ( addr == 0 )
        throw std::bad_alloc;
      return addr;
    }
    void * operator new ( size_t size, const std::nothrow_t &no_throw, const char * filename, int linenumber )
    {
      return _malloc_dbg( size, _CLIENT_BLOCK, filename, linenumber );
    }
    void * operator new [] ( size_t size, const char * filename, int linenumber )
    {
      void * addr = _malloc_dbg( size, _CLIENT_BLOCK, filename, linenumber );
      if ( addr == 0 )
        throw std::bad_alloc;
      return addr;
    }
    void * operator new [] ( size_t size, const std::nothrow_t &no_throw, const char * filename, int linenumber )
    {
      return _malloc_dbg( size, _CLIENT_BLOCK, filename, linenumber );
    }
    void operator delete( void *p, const char * filename, int linenumber )
    {
      _free_dbg(p,_CLIENT_BLOCK);
    }
    void operator delete [] ( void *p, const char * filename, int linenumber )
    {
      _free_dbg(p,_CLIENT_BLOCK);
    }
    # define DEBUG_NEW_HEAP new( __FILE__, __LINE__ )
    # define new DEBUG_NEW_HEAP
    #endif
    

    (参考:prev. topic

    【讨论】:

      【解决方案3】:

      Visual Studio 中的 CRT 内存调试功能大有帮助。您想要的额外内容需要记录每个分配。 CRT 为这种事情提供了_CrtSetAllocHook

      【讨论】:

      • 这是否也会捕获来自第三方 DLL 的分配?我碰巧有我的第三方库的调试 DLL。我曾考虑重载全局 new & delete 以捕获信息,但这不会扩展到我的第三方调试 DLL AFAIK。
      • 重载 new 和 delete 通常很麻烦,尤其是在使用不受控制的 DLL 时。 CRT alloc 挂钩的级别非常低。如果所有的 DLLs 都在运行时的 DLL 版本上,你应该状态良好,只要你能在 DLLs 做一堆分配之前设置钩子。如果一个或多个 DLL 链接到静态 CRT,那么您可能无法跟踪这些分配。
      【解决方案4】:

      你可以试试Valgrind

      【讨论】:

      • Valgrind 不支持 Windows...
      • 这是一个哭泣的耻辱。它支持 OS X 甚至 Android!
      【解决方案5】:

      如果你还没有看过这个,你可能想看看这里。它似乎是最近更新的。

      Sysinternals Suite By Mark Russinovich http://technet.microsoft.com/en-us/sysinternals/bb842062.aspx

      【讨论】:

      • 在我最初的问题中,我提到我已经尝试过 VMMap,这是我知道的套件中唯一的工具,它甚至可以远程帮助我满足我的需求。
      猜你喜欢
      • 1970-01-01
      • 2010-12-02
      • 2011-09-28
      • 2010-09-20
      • 1970-01-01
      • 2012-04-25
      • 1970-01-01
      • 2011-06-09
      相关资源
      最近更新 更多