C++ 什么Alloc API可以在内部调用VirtualAlloc/保留内存?

C++ 什么Alloc API可以在内部调用VirtualAlloc/保留内存?,c++,windows,winapi,dll,virtual-memory,C++,Windows,Winapi,Dll,Virtual Memory,我正在调试调试DLL中潜在的内存泄漏问题 在这种情况下,进程运行一个子测试,动态加载/卸载DLL,在测试过程中保留并提交了大量内存(1.3GB)。测试完成并卸载DLL后,仍保留大量内存(1.2GB) 我之所以说这个保留内存是由DLL分配的,是因为如果我使用一个发布DLL(没有其他更改,相同的测试),保留内存是~300MB,所以所有额外的保留内存都必须在调试DLL中分配 看起来在测试期间提交了大量内存,但在测试之后取消了提交(而不是释放到可用状态)。所以我想追踪谁保留/取消了这么大的内存。但在源代

我正在调试调试DLL中潜在的内存泄漏问题

在这种情况下,进程运行一个子测试,动态加载/卸载DLL,在测试过程中保留并提交了大量内存(1.3GB)。测试完成并卸载DLL后,仍保留大量内存(1.2GB)

我之所以说这个保留内存是由DLL分配的,是因为如果我使用一个发布DLL(没有其他更改,相同的测试),保留内存是~300MB,所以所有额外的保留内存都必须在调试DLL中分配

看起来在测试期间提交了大量内存,但在测试之后取消了提交(而不是释放到可用状态)。所以我想追踪谁保留/取消了这么大的内存。但在源代码中,没有调用VirtualAlloc,所以问题是:

  • VirtualAlloc是保留内存的唯一方法吗
  • 如果没有,还有什么API可以做到这一点?如果是,还有什么API会在内部调用VirtualAlloc?相当多的人在网上说HeapAlloc会在内部称之为VirtualAlloc?它是如何工作的
  • [这部分内容纯粹是实现细节,而不是应用程序应该依赖的内容,因此仅将其作为参考目的,而不是作为任何形式的正式文档或合同。也就是说,了解如何在后台实现这些内容是有一定价值的,即使只是为了调试目的。]

    是的,VirtualAlloc()函数是Windows中内存分配的主要函数。它是一个低级功能,如果您需要它的功能,操作系统会提供给您,但也是系统内部使用的功能。(准确地说,它可能不会直接调用VirtualAlloc(),而是VirtualAlloc()也会调用的更低级别的函数,比如NtalocateVirtualMemory(),但这只是语义,不会改变可观察的行为。)

    因此,HeapAlloc()是在VirtualAlloc()的基础上构建的,GlobalAlloc()和LocalAlloc()也是如此(尽管后两者在32位Windows中已经过时,基本上不应该被应用程序使用,而更喜欢显式调用HeapAlloc()

    当然,HeapAlloc()不仅仅是VirtualAlloc()的简单包装器。它添加了一些自己的逻辑。VirtualAlloc()总是以大块的方式分配内存,由系统的分配粒度定义,这是特定于硬件的(可通过调用GetSystemInfo()并读取
    system\u INFO.dwAllocationGranularity
    的值来检索)。HeapAlloc()允许您以所需的任何粒度分配较小的内存块,这更适合于典型的应用程序编程。在内部,HeapAlloc()处理调用VirtualAlloc()以获取一个大的块,然后根据需要对其进行分割。这不仅提供了一个更简单的API,而且效率更高

    请注意,C运行时库(CRT)提供的内存分配函数——即C的malloc()和C++的新操作符——是一个更高的级别。它们构建在HeapAlloc()之上(至少在Microsoft的CRT实现中)。在内部,它们分配相当大的内存块,基本上用作应用程序的“主”内存块,然后根据请求将其划分为更小的块。释放/删除这些块时,它们将返回到池中。再一次,这个额外的层提供了一个简化的接口(特别是编写独立于平台的代码的能力),并且在一般情况下提高了效率

    各种OS API提供的内存映射文件和其他功能也构建在虚拟内存子系统上,因此在内部调用VirtualAlloc()(或更低级别的等效程序)

    因此,基本上,正常Windows应用程序的最低级别内存分配例程是VirtualAlloc()。但这并不意味着它是通常用于内存分配的主要功能。只有在实际需要其附加功能时才调用VirtualAlloc()。否则,请使用标准库的内存分配例程,或者如果您有一些令人信服的理由避免使用这些例程(如不链接到CRT或创建自己的自定义内存池),请调用HeapAlloc()

    还要注意,您必须始终使用与分配内存所用的机制相对应的机制来释放内存。仅仅因为所有内存分配函数最终都调用VirtualAlloc(),并不意味着您可以通过调用VirtualFree()释放内存。如上所述,这些其他函数在VirtualAlloc()之上实现额外的逻辑,因此需要调用它们自己的例程来释放内存。仅当通过调用VirtualAlloc()自行分配内存时,才调用VirtualFree()。如果内存是用HeapAlloc()分配的,则调用HeapFree()。对于malloc(),调用free();要获取新信息,请调用delete


    至于你问题中描述的具体情况,我不清楚你为什么担心这一点。记住保留内存和提交内存之间的区别是很重要的。Reserved仅仅意味着地址空间中的这个特定块已被保留供进程使用。无法使用保留块。为了使用内存块,必须提交它,这是指在页文件或物理内存中为内存分配备份存储的过程。这有时也称为映射。保留和提交可以作为两个单独的步骤进行,也可以同时进行。例如,您可能想保留一个连续的地址空间供将来使用,但实际上您还不需要它,所以您不提交它。已保留但未提交的内存实际上未分配

    事实上,所有这些保留内存可能根本不是泄漏。调试中使用的一种相当常见的策略是保留特定范围的me