c++ (windows)中的分配数及其可预测性

Allocation numbers in C++ (windows) and its predictibility

本文关键字:可预测性 分配 windows c++      更新时间:2023-10-16

我使用_CrtDumpMemoryLeaks来识别我们软件中的内存泄漏。我们在多线程应用程序中使用第三方库。这个库确实存在内存泄漏,因此在我们的测试中,我们希望识别出那些属于我们的,并丢弃那些我们无法控制的。

我们使用持续集成,所以新的函数/算法/bug修复一直在添加。

所以问题是——是否有一种安全的方法来识别那些属于我们的泄漏和那些属于第三方库的泄漏。我们考虑过使用分配号,但这样安全吗?

在一个大型应用程序中,我研究全局newdelete操作符被覆盖(例如:参见如何正确替换global new &删除操作符)和使用私有堆(例如。HeapCreate)。第三方库将使用进程堆,因此分配将被清楚地分开。

坦率地说,我认为你在分配号码上走不了多远。为应用程序/库使用显式的单独堆(甚至可能在您自己的应用程序中使用单独的每个组件堆)将更易于管理。考虑一下,你可以为每个分配的块添加你自己的特定于应用程序的头,从而启用非常花哨的内存跟踪。例如,为了调试,捕获整个调用堆栈的分配是可能的。启用每个组件计费。

您可以使用microsoft的堆调试库来完成此操作,而无需使用任何第三方解决方案。根据我从前面的问题中学到的,您应该确保代码中分配的所有内存都是通过调用_malloc_dbg来分配的,其中第二个参数设置为_CLIENT_BLOCK。然后你可以用_CrtSetDumpClient设置一个回调函数,这个回调函数将只接收关于客户端块的信息,而不是其他的。

您可以轻松地使用预处理器将所有调用转换为mallocfree,以实际调用它们的调试版本(例如_malloc_dbg);只要看看Visual Studio自带的crtdbg.h是如何完成的。

对我来说,棘手的部分是弄清楚如何覆盖newdelete操作符来调用_malloc_dbg等调试函数。可能很难找到一种解决方案,在这种解决方案中,只有您自己代码中的new s和delete s受到影响,而在第三方库中不受影响。

您可能需要使用Microsoft提供的DebugDiag Tool。获取有关该工具的完整信息我们可以参考:http://www.microsoft.com/en-sg/download/details.aspx?id=40336

DebugDiag可用于识别各种问题。我们可以按照步骤找到泄漏(我们的和第三方模块):

  1. 在规则类型"Native(非。net) Memory and Handle Leak"下配置DebugDiag。
  2. 现在重新运行应用程序一段时间并捕获转储文件。我们还可以配置在指定的时间间隔后捕获转储文件。
  3. 现在我们可以在"性能分析器"下使用DebugDiag打开/分析捕获的转储文件。

一旦分析完成,DebugDiag将自动生成报告,并为您提供可能发生泄漏的模块/DLL信息(有概率)。在此之后,我们从DebugDiag工具中获得关于模块的信息,我们可以通过进行静态代码分析来专注于特定的模块。如果模块属于第三方DLL,我们可以将DebugDiag报告共享给他们。除此之外,如果使用适当的PDB文件运行/附加应用程序,DebugDiag还提供了可能发生内存泄漏的调用堆栈。

这些信息在过去调试基于windows的应用程序内存泄漏时非常有用。希望以上信息会有用。

答案实际上取决于第三部分库的实际实现。它是否只泄漏一致数量的项,或者是否依赖于(例如)线程的数量、库中使用的函数等?什么时候进行拨款?

即使这样,无论库的使用情况如何,泄漏的数量都是一致的,我也会犹豫是否使用这个分配号。无论如何,试一试吧。如果所有的分配都很早就完成了,并且它们不依赖于任何"你的"代码,那么它就可以工作-这是一件非常简单的事情。但是尝试添加例如static std::vector<int>(100),看看静态变量中的内存分配是否会影响分配数量……如果是这样,那么这个方法可能注定要失败(除非您对静态对象有非常严格的规则)。

使用单独的堆(替换new/delete操作符)将是正确的解决方案,因为这可能也可以扩展到收集其他统计数据[如分配的数量,以检测代码中过度分配的部分-当然,这必须根据代码实际做什么来分析]。

新的Doug Lea malloc包含了mspace抽象。mspace是一个单独的堆。在我们的几个100K NCSL应用程序中,我们为代码的不同部分使用了十几个不同的mspace。我们使用分配器让STL容器从右空间分配内存。

一些好处

  • 第三方代码不使用mspace,所以他们的分配(和泄漏)不会与我们的
  • 混合
  • 我们可以查看每个mspace的内存使用情况,看看哪段代码可能有内存泄漏
  • 任何内存损坏都包含在一个mspace内,从而限制了我们需要查看的代码量。