使用分配器挂钩时如何检索被释放的字节?

Posted

技术标签:

【中文标题】使用分配器挂钩时如何检索被释放的字节?【英文标题】:How to retrieve bytes being freed when using Allocator hooks? 【发布时间】:2017-03-18 05:05:11 【问题描述】:

我正在尝试在我的应用程序中实现一个基本的内存分析器(是的,我知道存在强大的外部软件)。我一直在研究一些关于如何使用分配挂钩的在线示例,并且我得到了计算内存分配的部分。它只是使用CtrSetAllocHook 安装一个自定义malloc,看起来或多或少类似于以下内容:

int64_t memUsage (0);
int __cdecl MyAllocHook(
    int      nAllocType,
    void   * pvData,
    size_t   nSize,
    int      nBlockUse,
    long     lRequest,
    const unsigned char * szFileName,
    int      nLine
)

    if (nAllocType ==_HOOK_ALLOC)
    
        memUsage += nSize;
    
    else if (nAllocType == _HOOK_FREE)
    
    //HOW-TO: memUsage -= nSize; ???
    

    return(TRUE);

然而,当分配内存时,很容易增加一个计数器intvariable,它检索从nSize 分配的东西的大小,但我不知道在释放内存时我应该如何减少这样的计数器。原因是当调用malloc释放内存时(即nAllocType参数=_HOOK_FREE_),上面函数的参数nSize总是等于0。这意味着我们无法存储在 malloc 挂钩中释放的字节数。

有人可以帮助我了解当malloc 在空闲内存模式下调用时,我如何使用分配挂钩来减少memUsage 计数器?

【问题讨论】:

您知道堆管理将有关堆块大小的信息存储在实际数据旁边的某个位置。当您减少pvData(按地址大小)时,您可能会发现要释放的块大小。 Google 用于“MSVC 堆管理”(例如 CRT Debug Heap Details 可能会有所帮助。) 恐怕你的标签有点误导。 C++ 有一个分配器的“概念”,它与您的问题无关。 (c++ 值得怀疑。)_CrtSetAllocHook 似乎与 MS CRT 有关。 (恕我直言msvcrt 是最接近的。)实际上,C++ 标准没有提到 new 和 delete 必须在内部使用什么。对于 Microsoft 的 C++,它可能也在他们的 malloc()free() 实现中使用。 @Scheff 感谢您的 cmets。但是,恐怕您所说的很多晦涩之处。首先,由于 void 指针的算术运算是非法的,因此减少 pvData 意味着什么?其次,在阅读了您建议的文档后,我不知道如何使用 pvData 来取回内存大小。直觉上我认为(size_t*)(pvData)(((size_t *) ptr) - 1) 可以给它,但不是。 需要一些时间才能再次找到它,但我做到了:Win32 Debug CRT Heap Internals 您应该考虑到堆帧在调试和发布二进制文件中可能不同(但我不确定对此...) 【参考方案1】:

在 Visual Studio 6.0 和 2008 的调试模式下(您使用的是什么版本?) pvData 指向的数据前面有一个 _CrtMemBlockHeader 结构,其中包含有关内存的信息。

递减 pvData 以到达标头的开头并从标头结构中获取插槽 nDataSize。

int MyAllocHook(..) 

    else if (nAllocType == _HOOK_FREE) 
    
        size_t headerSize = sizeof(_CrtMemBlockHeader);
        _CrtMemBlockHeader* pHead;
         size_t ptr = (size_t) pvData - headerSize;
         pHeader = (_CrtMemBlockHeader*) (ptr);
         size_t dataSize = pHeader->nDataSize;

另外,请参阅此处的第二个答案(针对 Visual Studio 2008):

What useful things can I do with Visual C++ Debug CRT allocation hooks except finding reproduceable memory leaks?

【讨论】:

谢谢,它不仅成功了,还帮助最终理解了 mem 块是如何处理的。【参考方案2】:

虽然我更喜欢@Angela Richardson 对我的问题的回答,因为它指出了在 Visual Studio 中提供的更灵活的解决方案,通过使用 _CrtMemBlockHeader,我认为在此注册 Visual Studio 也允许使用_msize(void* ptr)的简单解决方案

【讨论】:

以上是关于使用分配器挂钩时如何检索被释放的字节?的主要内容,如果未能解决你的问题,请参考以下文章

.NET 可用内存使用情况(如何防止过度分配/释放内存给操作系统)

C 和 C++:释放已分配指针的一部分

如何验证两个检查点之间是否已释放所有内存分配?

堆的分配和释放

Unix系统编程()在堆上分配内存

动态内存