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

时间:2009-01-28 13:53:53

标签: .net garbage-collection

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

我们希望在程序的某些位置添加一个例程来检查托管堆中是否存在某些对象。

2 个答案:

答案 0 :(得分:6)

  1. 安装“Windows调试工具”。

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

    湾您将使用WinDbg.EXE(本机Windows调试器)和SOS.DLL(a.k.a。“Son of Strike”),即托管代码的WinDbg扩展。

    ℃。默认安装位置是“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>

         

    ...

         

    <对象>

         

    每个类(类型)都包含一个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”>

    ℃。示例:转储DataTable对象。

    • (在WinDbg中)!dumpobj 0137ecd8

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

    • !dumpobj< “价值”>
  10.   

    添加,如果要跟踪大对象分配,这里是如何在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. 恢复:

答案 1 :(得分:3)

您需要使用debugging/profiling API来执行此操作 - 我不建议您使用“普通”应用程序。