如何迭代.NET托管堆中存在的对象?

sth*_*ers 2 .net garbage-collection

.NET API中是否有一种方法可以迭代托管堆中存在的托管对象?

我们想在程序的某些点添加一个例程来检查托管堆中是否存在某些对象.

Bob*_*Bob 6

  1. 安装"Windows调试工具".

    一个.链接:http://www.microsoft.com/whdc/devtools/debugging/default.mspx

    湾 您将使用WinDbg.EXE(本机Windows调试器)和SOS.DLL(又名"Strike之子"),即托管代码的WinDbg扩展.

    C.默认安装位置是"C:\ Program Files\Debugging Tools for Windows".

  2. 运行您的托管流程.

  3. 运行WinDbg并单击"文件 - >附加到进程..."

  4. 从列表中选择您的流程.

  5. WinDbg会在附加到您的进程时自动中断(停止)执行.

  6. 在WinDbg的命令行输入".load sos.dll"(是的,使用前面的".")来加载攻击之子.

  7. 输入"!help"以查看罢工之子提供的命令/功能列表.

  8. 键入"!traverseheap -xml heap.xml"将进程堆转储到WinDbg目录中的heap.xml(例如,C:\ Program Files\Debugging Tools for Windows").

    一个.遍历堆并将堆转储到文件可能需要非常长的时间.WinDbg将" BUSY "发布到其状态并打印"." - s表示进度.

    湾 通常,heap.xml的结构如下:

    <类型ID>

    ...

    <Objects>

    每个类(类型)都包含一个ID,每个对象都包含其类型ID,托管地址和大小.

  9. 对heap.xml使用findstr(命令提示符)来通过堆grep你的方式,使用WinDbg来转储对象.

    一个.示例:查找DataTable类的类型ID.

    • findstr"DataTable"heap.xml

      输出:<type id ="1002"name ="System.Data.DataTable"/>

    湾 示例:查找所有DataTable对象.

    • findstr"typeid = \"1002 \""heap.xml

      输出:<object address ="0x0137ECD8"typeid ="1002"size ="296">

    C.示例:转储DataTable对象.

    • (在WinDbg中)!dumpobj 0137ecd8

    d.示例:转储成员对象.成员对象的地址存储在成员的包含对象转储的"值"字段中.

    • !dumpobj <"价值">

.

添加,如果要跟踪大对象分配,这里是如何在LOH分配中打破CLR.在打破时,点击"k"以查看callstack.

运行WinDbg并附加如下.

  1. 将Microsoft的符号服务器添加到符号路径:
  2. 重新加载符号:
    • .reload
  3. 重新加载运行时垫片:
    • .reload/f mscorwks.dll
  4. 打破UP分配:
    • bp mscorwks!WKS :: gc_heap :: allocate_large_object
  5. 中断MP分配:
    • bp mscorwks!SVR :: gc_heap :: allocate_large_object
  6. 确认断点:
    • BL
  7. 恢复:
    • G