在我的过程中,所有这些未提交的,保留的内存是什么?

时间:2010-12-21 19:47:46

标签: windows memory-management sysinternals

我正在使用来自SysInternals的VMMap查看我的Win32 C ++进程在WinXP上分配的内存,我看到一堆分配,其中已分配内存的一部分被保留但未提交。据我所知,从我的阅读和测试来看,C ++程序中使用的所有常见内存分配器(例如,malloc,new,LocalAlloc,GlobalAlloc)总是分配完全提交的内存块。 堆是保留内存但在需要之前不提交内存的代码的常见示例。我怀疑其中一些块是Windows / CRT堆,但似乎有更多这些类型的块比我预期的堆更多。我看到我的进程中有30个这样的块,大小在64k到8MB之间,我知道我的代码从不故意调用VirtualAlloc来分配保留的,未提交的内存。

以下是VMMap的几个示例:http://www.flickr.com/photos/95123032@N00/5280550393/

还有什么会分配这样的内存块,其中大部分是保留但未提交?我的流程有30堆是否有意义?感谢。

3 个答案:

答案 0 :(得分:8)

我想通了 - 它是通过调用malloc分配的CRT堆。如果使用malloc分配大块内存(例如,2 MB),则会分配一个已提交的内存块。但是如果你分配较小的块(比如177kb),那么它将保留1 MB的内存块,但只提交大约你要求的内容(例如,我的177kb请求为184kb)。

当你释放那个小块时,那个较大的1 MB块不会返回给操作系统。除了4k之外的所有内容都是未提交的,但仍保留完整的1 MB。如果您再次呼叫malloc,它将尝试使用该1 MB块来满足您的请求。如果它不能满足你的请求与它已经保留的内存,它将分配一个新的内存块,这是以前分配的两倍(在我的情况下,它从1 MB到2 MB)。我不确定这种加倍的模式是否会继续。

要将释放的内存实际返回给操作系统,可以调用_heapmin。我认为这会使未来的大型分配更有可能成功,但它将全部依赖于内存碎片,如果分配失败(?),可能已经调用了heapmin,我不确定。由于heapmin会释放内存(需要时间),因此性能也会受到影响,然后malloc需要在需要时再次从操作系统重新分配它。此信息适用于Windows / 32 XP,您的里程可能会有所不同。

更新:在我的测试中,heapmin完全没有做任何事情。 malloc堆仅用于小于512kb的块。即使malloc堆中存在MB连续的可用空间,它也不会将其用于超过512kb的请求。在我的情况下,这个释放,未使用但保留的malloc内存占据了我的进程2GB地址空间的大部分,最终导致内存分配失败。由于heapmin没有将内存返回给操作系统,除了重启我的进程或编写自己的内存管理器之外,我还没有找到解决这个问题的任何方法。

答案 1 :(得分:0)

它们可能是加载到您的进程中的DLL吗? DLL(和可执行文件)是内存映射到进程地址空间的。我相信这最初只是预留空间。该空间由文件本身(至少在最初)而不是页面文件支持。

只有实际触及的代码才能被访问。如果我正确理解了术语,那就是它被提交的时候。

您可以通过在调试器中运行应用程序并查看加载的模块并将其位置和大小与VMMap中显示的内容进行比较来确认。

答案 2 :(得分:0)

每当在应用程序中创建一个线程时,将在线程的调用堆栈的地址空间中保留一定(可配置)的内存量。除非您的线程实际上需要所有内存,否则不需要提交所有保留的内存。所以只需要提交一部分。

如果需要超过提交的内存量,则可以获得更多的系统内存。

实际考虑因素是保留内存是堆栈大小的硬限制,会减少应用程序可用的地址空间。但是,通过仅提交部分保留,我们不需要在需要之前从系统中消耗相同数量的内存。

因此,每个线程都可能拥有一部分保留的未提交内存。我不确定在这种情况下页面类型是什么。