代码之家  ›  专栏  ›  技术社区  ›  BuschnicK

跟踪C++内存分配

  •  44
  • BuschnicK  · 技术社区  · 17 年前

    对内存泄漏感兴趣,这似乎是大多数工具都在试图找到的,但实际上是为应用程序创建内存使用情况配置文件。理想的输出是一个大的函数名列表加上一段时间内分配的最大字节数,或者更好的是,一段时间内堆的图形表示。横轴是时间,纵轴是堆空间。每个函数都将获得自己的颜色,并根据分配的堆字节绘制线条。识别分配的对象类型也有额外的好处。

    我们的想法是找到内存瓶颈/可视化哪些函数/线程消耗了最多内存,并且应该针对这些函数/线程进行进一步优化。

    我已经简要介绍了Purify、BoundsChecker和AQTime,但它们似乎不是我想要的。Valgrind看起来很合适,但我在Windows上。 Memtrack

    8 回复  |  直到 6 年前
        1
  •  34
  •   anon anon    17 年前

    使用Valgrind及其工具Massif。其示例输出(其一部分):

    99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
    ->49.74% (10,000B) 0x804841A: main (example.c:20)
    | 
    ->39.79% (8,000B) 0x80483C2: g (example.c:5)
    | ->19.90% (4,000B) 0x80483E2: f (example.c:11)
    | | ->19.90% (4,000B) 0x8048431: main (example.c:23)
    | |   
    | ->19.90% (4,000B) 0x8048436: main (example.c:25)
    |   
    ->09.95% (2,000B) 0x80483DA: f (example.c:10)
      ->09.95% (2,000B) 0x8048431: main (example.c:23)
    

    因此,您将获得详细信息:

    • 谁分配了内存(上例中的函数:g()、f()和main());您还可以获得完整的回溯,从而分配函数,
    • 事情发生的时候,,
    • 它占所有分配内存的百分比是多少(g:39.7%,f:9.95%,main:49.7%)。

    这是 Massif manual

    另外,我刚读到你在Windows上。不过我会留下答案,因为它给出了一幅图片,说明了您可以从一个可能的工具中获得什么。

        2
  •  21
  •   Gang YIN    7 年前

    微软拥有完善的内存跟踪功能。然而,由于某些原因,它们在开发人员社区中并不是很有名。这些是CRT调试函数。好的起点是 CRT Debug Heap functions .

    有关更多详细信息,请查看以下链接

    1. Heap state reporting functions
    2. Tracking heap allocation requests
        3
  •  17
  •   Tim Cooper    14 年前

    对于一个通用C++内存跟踪器,您需要重载以下内容:

    global operator new
    global operator new []
    global operator delete
    global operator delete []
    any class allocators
    any in-place allocators
    

    棘手的一点是获取有用的信息,重载运算符只有分配器的大小信息和删除的内存指针。答案之一是使用宏。我知道。肮脏的示例-放置在包含在所有源文件中的标题中:

    #undef new
    
    void *operator new (size_t size, char *file, int line, char *function);
    // other operators
    
    #define new new (__FILE__, __LINE__, __FUNCTION__)
    

    并使用以下内容创建源文件:

    void *operator new (size_t size, char *file, int line, char *function)
    {
      // add tracking code here...
      return malloc (size);
    }
    

    只有在类作用域中未定义任何新运算符时,上述操作才有效。如果您在类范围内有一些,请执行以下操作:

    #define NEW new (__FILE__, __LINE__, __FUNCTION__)
    

    并将“新类型”替换为“新类型”,但这可能需要更改大量代码。

    由于它是一个宏,删除内存跟踪器非常简单,因此标题变为:

    #if defined ENABLED_MEMORY_TRACKER
    #undef new
    
    void *operator new (size_t size, char *file, int line, char *function);
    // other operators
    
    #define NEW new (__FILE__, __LINE__, __FUNCTION__)
    #else
    #define NEW new
    #endif
    

    以及实施文件:

    #if defined ENABLED_MEMORY_TRACKER
    void *operator new (size_t size, char *file, int line, char *function)
    {
      // add tracking code here...
      return malloc (size);
    }
    endif
    
        4
  •  4
  •   Adelhart    6 年前

    对@Skizz的回答

    std::source_location 而不是像这样的宏 __FILE__ __LINE__ .

    (由于这是一个重大的简化,我认为它应该得到一个单独的答案)。

        5
  •  0
  •   oz10    17 年前

    在MacOSX上,您可以使用代码分析工具Shark来实现这一点,IIRC。

        6
  •  0
  •   Totoro    10 年前

    在Xcode上,您可以使用工具来跟踪分配、VM使用和其他几个参数。主要受iOS开发者欢迎,但值得一试。

        7
  •  0
  •   araud    10 年前

    “堆随时间变化的图形表示”-接近您要查找的内容在中实现 Intel(R) Single Event API ,详情请参阅 this article (放在这里相当大)。 Memory block allocations over time

        8
  •  0
  •   gavinb    7 年前

    VisualStudioIDE具有内置的堆分析支持(自2015年以来),这可能是最容易开始的。它具有随时间变化的堆使用情况的图形视图,并且可以按函数/方法跟踪分配。

    heap profiling

    CRT还具有调试和概要文件支持,这更详细、更低级。您可以使用其他工具跟踪数据并绘制结果:

    特别是看 _CrtMemCheckpoint 以及相关功能。