【问题标题】:Making sense of UMDH compare output理解 UMDH 比较输出
【发布时间】:2014-11-11 14:36:21
【问题描述】:

背景

我已经设置了一个测试工具来测试我正在为一个项目开发的 DLL 中的一组函数。

我想验证函数在 Windows 系统上的内存泄漏为零。

我已经正确设置了 UMDH,并且能够获得两个堆转储之间的比较文件。甚至堆栈跟踪也显示得很好。

问题

diff 的输出让我感到困惑,我希望有人能帮助解释为什么我得到了我得到的输出。

比较日志的输出:

+      56 (     56 -      0)      1 allocs  BackTrace9C160
+       1 (      1 -      0)    BackTrace9C160  allocations

我将 log1 和 log2 设置为分开 1 个整数分配,只是为了验证我的设置。

确实,它只显示了 1 个分配,但是,它是说前后有 56 字节的变化。我只希望 sizeof(int) 以字节为单位变化。在我的系统上,int 分配的大小是 4 字节,所以我希望看到 +4,而不是 +56。

同样,在日志之间运行的唯一代码行是

new int; //purposely leak memory

有什么解释吗?

附加信息:

IDE/编译器:Visual Studio 2010

应用程序是 64 位

涉及一个 DLL(但在这个简单的 int 分配示例中我什至没有调用它)

如果我注释掉泄漏,我得到零分配和 +0 字节。所以我认为这可以验证应用程序中的其他任何地方都没有额外的字节,只需从上面显示的那一行...

解决方案

请参阅下面的 SleuthEye 解决方案。另外,我添加了一条评论作为对解决方案的评论,我认为这对最终使用此问题的人有益:

此外,如果您在 .exe 的发布版本上运行此程序,并且还在运行目录中包含程序调试数据库,则 umdh 将提取源文件名和内存泄漏的行号,同时保持准确的字节数数。就内存泄漏搜索而言,这为您提供了调试和发布版本的好处。

【问题讨论】:

  • 我认为这是由于使用 debug heap 时分配的额外字节所致。

标签: c++ c windows debugging 64-bit


【解决方案1】:

56 字节是由 C 运行时库 (CRT) 在使用调试堆时分配的额外内存产生的,如 MSDN 中所述。

查看 dbbint.h,其中_CrtMemBlockHeader 结构定义为:

#define nNoMansLandSize 4

typedef struct _CrtMemBlockHeader
{
        struct _CrtMemBlockHeader * pBlockHeaderNext;
        struct _CrtMemBlockHeader * pBlockHeaderPrev;
        char *                      szFileName;
        int                         nLine;
#ifdef _WIN64
        /* These items are reversed on Win64 to eliminate gaps in the struct
         * and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is
         * maintained in the debug heap.
         */
        int                         nBlockUse;
        size_t                      nDataSize;
#else  /* _WIN64 */
        size_t                      nDataSize;
        int                         nBlockUse;
#endif  /* _WIN64 */
        long                        lRequest;
        unsigned char               gap[nNoMansLandSize];
        /* followed by:
         *  unsigned char           data[nDataSize];
         *  unsigned char           anotherGap[nNoMansLandSize];
         */
} _CrtMemBlockHeader;

后面是为int 分配的内存,然后是额外的 4 字节“NoMansLand”缓冲区。因此,对于 64 位应用程序,为单个 int 的测试用例分配的总内存为 sizeof(_CrtMemBlockHeader)+sizeof(int)+4 = 48+4+4 = 56

请注意,在发布版本(未分配 _CrtMemBlockHeader)上运行相同的分析会产生以下比较日志输出:

+       4 (      4 -      0)      1 allocs  BackTrace2
+       1 (      1 -      0)    BackTrace2  allocations

【讨论】:

  • 这正是我想要的。我的印象是它需要调试版本才能运行这种分析。这现在完全有道理,并解释了为什么 valgrind 的行为不同。这是因为它作用于发布版本,并且没有此处描述的开销。
  • 另外,如果你在一个release .exe上运行这个程序,并且在运行目录中包含程序调试数据库,umdh也会拉取源文件名和内存泄漏的行号—— - 同时保持准确的字节数。就内存泄漏搜索而言,这为您提供了调试和发布版本的好处。
【解决方案2】:

您可以使用UMDH Diff Viz 工具轻松读取比较输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-11
    • 2011-04-28
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多