讲述内存碎片的故事(与内存泄漏相反)?

时间:2009-09-28 15:25:45

标签: windows memory-management memory-leaks windbg

首先我意识到泄漏会严重破坏记忆,但请耐心等待。

  • 使用WinDbg并附加到进程:使用!heap(或其他WinDbg命令),如果我处理内存碎片而不是泄漏,我应该看到什么?例如,我可以使用“!heap stat”和“!heap stat -h handle”来对生成泄漏的代码进行归零;但这些相同的返回值中是否有某些暗示碎片的东西?
  • XP和Vista之间的内存分配是否发生了根本变化?特别是,与DLL和其他库加载相关?我们一直在开发XP,因此我对Vista不熟悉,但事实证明,当我们在Vista上安装相同的二进制文件时,我们在XP上看到的某些内存问题就会消失。

谢谢!

3 个答案:

答案 0 :(得分:9)

有几种不同的碎片:地址空间碎片和堆碎片。前者可能导致无法扩展托管或非托管堆,或者无法加载DLL,后者可能会在调用new时导致内存分配失败。

您可以使用!address -summary来概述地址空间。这告诉您有多少空间是空闲,已提交,用于DLL映射,虚拟地址描述符(元数据)等.sysinternals VMMap工具为您提供了它的图形视图,而无需调试器。

对于堆碎片,!heap -s的输出应该包括碎片非托管堆的一些指示,例如:

00970000 00001002   64576  39232  49736   5732  1314   448    0      1   L  
    External fragmentation  14 % (1314 free blocks)
    Virtual address fragmentation  21 % (448 uncommited ranges)

您可以使用!heap -stat进行深入研究,例如!heap -stat -h 00970000给出上面的输出,这将告诉你分配大小等的分布。这对于看看你是否有大量的小对象很有用,假设你没有使用低碎片堆,例如:

0:057> !heap -stat -h 00970000 
 heap @ 00970000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    134 c0c8 - e7f0a0  (50.72)
    18 ee22 - 165330  (4.88)
    8c 26f9 - 15502c  (4.66)
    a4 1ffc - 147d70  (4.48)

希望这有帮助。

答案 1 :(得分:2)

对不起,我无法帮助解决碎片问题,所以我只想解决你的第二个问题。

Vista引入了ASLR,它改变了DLL的加载方式。有关详细信息,请参阅此wiki entry,有关更具体的讨论this post可能会有用。

答案 2 :(得分:2)

从Windows Vista开始,默认启用新的内存管理器,称为低碎片堆(m2)。

MS Description

对于Windows XP,您可以使用以下代码启用低碎片堆:

HANDLE heaps[1025];
DWORD nheaps = GetProcessHeaps((sizeof(heaps) / sizeof(HANDLE)) - 1, heaps);
for (DWORD i = 0; i < nheaps; ++i) {
  ULONG  enableLFH = 2;
  HeapSetInformation(heaps[i], HeapCompatibilityInformation, &enableLFH, sizeof(enableLFH));
}