• 在VMMap中跟踪不可用的虚拟内存


    VMMap是一个很好的系统内部工具,它可以可视化特定进程的虚拟内存,并帮助理解内存的用途。它有线程堆栈、映像、Win32堆和GC堆的特定报告。有时,VMMap会报告不可用的虚拟内存,这与可用内存不同。下面是32位进程(总共有2GB虚拟内存)的VMMap报告示例:

    这种“不可用”的内存从何而来,为什么不能使用?Windows虚拟内存管理器具有64KB的分配粒度。当直接用VirtualAlloc分配内存并要求小于64KB(比如16KB)时,VirtualAlloc返回64KB边界上的地址。然后分配前四页(16KB),其余48KB标记为未使用。无法通过执行另一个分配来获取此内存,因为VirtualAlloc将始终返回驻留在64KB边界上的地址。那么,这个内存是不可用的。
    VMMap中的fragmentation视图使问题更加明显。在下面的屏幕截图中,黄点是4KB区域,可以分配和使用,而灰色矩形是60KB区域,不能使用。当整个地址空间都是这些不可用的区域时,你得到的虚拟内存就没有你想象的那么多了。

    幸运的是,很容易找到违规分配的来源。本质上,我们正在寻找分配大小小于64KB(或者更好:不能被64KB平均整除)的VirtualAlloc调用。您可以使用VMMap本身(它具有跟踪模式)跟踪这些分配,也可以附加WinDbg并设置断点:

    0:000> bm kernelbase!VirtualAlloc* "r $t0 = poi(@esp+8); .if (@$t0 % 0x10000 != 0) { .printf "Unusable memory will emerge after allocating %d bytes", @$t0; kb 4 } .else { gc }"
      1: 76c03e8a          @!"KERNELBASE!VirtualAllocExNuma"
      2: 76bcd532          @!"KERNELBASE!VirtualAlloc"
      3: 76c03e66          @!"KERNELBASE!VirtualAllocEx"
    0:000> g
    Unusable memory will emerge after allocating 4096 bytes
    ChildEBP RetAddr  Args to Child              
    00defd48 010a4e34 00000000 00001000 00003000 KERNELBASE!VirtualAlloc
    00defe2c 010a5f25 00000000 00000000 7eaa7000 FourKBLeak!allocate_small+0x34
    00deff18 010a6989 00000001 012ba870 012bae98 FourKBLeak!main+0x35
    00deff68 010a6b7d 00deff7c 7529919f 7eaa7000 FourKBLeak!__tmainCRTStartup+0x199

    此断点确保传递给VirtualAlloc的分配大小可被64KB整除。否则,断点将停止并打印出有问题的分配和调用堆栈;否则,它将继续执行。这将使捕获小分配的源变得非常容易,并有望修复它们。

  • 相关阅读:
    Angularjs 设置全局变量的3种方法
    prevent to do sth 与 prevent sb (from) doing 用法
    软件测试技术对程序员的重要性
    Javascript中setTimeout()以及clearTimeout( )的使用
    Javascript异步编程的常用方法
    软件设计原则总结
    为sublime Text3 安装插件JS Format
    javascript中 if(变量)和if(变量==true)的区别
    Ping 命令
    ipconfig
  • 原文地址:https://www.cnblogs.com/yilang/p/12033563.html
Copyright © 2020-2023  润新知