【问题标题】:In Windbg how to get the whole content from !do Command在 Windbg 中如何从 !do 命令获取全部内容
【发布时间】:2014-10-15 15:42:28
【问题描述】:

我目前正在处理 .NET 应用程序的内存问题,我正在使用 Windbg 调试问题我遇到了内存问题,但在调查期间!do 命令正在获取对象其内容过大但命令显示的内容被截断,有没有办法可以完全从 !do 命令获取内容?

命令的结果如下所示:

0:000> !do [Address]
Name:        System.Byte[]
MethodTable: ...
EEClass:     ...
Size:        1048600(0x100018) bytes
Array:       Rank 1, Number of elements 1048576, Type Byte
Content:     [This is the content that its getting truncated]
Fields:
None

【问题讨论】:

  • 必须使用!do 还是可以使用!da 转储数组?
  • 我应该可以使用!da,有什么区别?
  • !da 将为您提供元素的地址,以便您可以对它们执行!do

标签: .net memory windbg sos


【解决方案1】:

由于您有一个byte 数组,您可以使用db 转储原始内存。我创建了一个值为 0、1、2、... 2000 的 byte 数组并将其丢弃:

0:000> !do 0x020a3560 名称:System.Byte[] 方法表:73504588 EE类:7319229c 大小:2012(0x7dc)字节 数组:排名 1,元素数 2000,类型字节 内容:...................... !"#$%&'()*+,-./0123456789 :;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~。 领域: 没有 0:000>分贝0x020a3560 0x020a3560+07dc 020a3560 88 45 50 73 d0 07 00 00-00 01 02 03 04 05 06 07 .EPs............ 020a3570 08 09 0a 0b 0c 0d 0e 0f-10 11 12 13 14 15 16 17 ...... 020a3580 18 19 1a 1b 1c 1d 1e 1f-20 21 22 23 24 25 26 27 ........ !"#$%&' 020a3590 28 29 2a 2b 2c 2d 2e 2f-30 31 32 33 34 35 36 37 ()*+,-./01234567 020a35a0 38 39 3a 3b 3c 3d 3e 3f-40 41 42 43 44 45 46 47 89:;?@ABCDEFG 020a35b0 48 49 4a 4b 4c 4d 4e 4f-50 51 52 53 54 55 56 57 HIJKLMNOPQRSTUVW 020a35c0 58 59 5a 5b 5c 5d 5e 5f-60 61 62 63 64 65 66 67 XYZ[\]^_`abcdefg 020a35d0 68 69 6a 6b 6c 6d 6e 6f-70 71 72 73 74 75 76 77 hijklmnopqrstuvw 020a35e0 78 79 7a 7b 7c 7d 7e 7f-80 81 82 83 84 85 86 87 xyz{|}~...... 020a35f0 88 89 8a 8b 8c 8d 8e 8f-90 91 92 93 94 95 96 97 ...... ...(剪断)...

前 4 个字节是方法表(73504588),接下来的 4 个字节是数组的长度(0x07D0,或 0n2000)。那么之后的所有字节都是数据。

【讨论】:

  • 0x020a3560+07d0 是怎么想出来的?从 "Size: 2012(0x7dc)" 到 "0x07D0" 的转换以及从 73504588 到 0x020a3560 的方法表的转换是什么?
  • 糟糕,它真的应该是0x7DC(2012,整个对象的大小)而不是0x7D0(2000,数组中的元素数量)。我根本没有使用 MethodTable,只是对象的地址(你暗示你在问题中拥有)。我只是注意到当你转储数组时,前 4 个字节是什么。
【解决方案2】:

Patrick 的回答对于 Byte[] 或其他简单类型是可以的。如果您需要相同的引用类型,请尝试 !daSOS!mdtSOSEXextension。

首先,让我们看看!da 是如何工作的:

0:077> *** Get method table to be specific about the object
0:077> !dumpheap -stat -type PointF[]
total 290 objects
Statistics:
      MT    Count    TotalSize Class Name
7ae3a114      290         8360 System.Drawing.PointF[]
Total 290 objects

0:077> *** Get individual arrays
0:077> !dumpheap -mt 7ae3a114
 Address       MT     Size
3be693a4 7ae3a114       28     
3be69400 7ae3a114       28   
...
total 290 objects
Statistics:
      MT    Count    TotalSize Class Name
7ae3a114      290         8360 System.Drawing.PointF[]
Total 290 objects

0:077> *** Pick one for demo purposes. Output is not that useful.
0:077> !do 3be693a4 
Name: System.Drawing.PointF[]
MethodTable: 7ae3a114
EEClass: 7adeb1cc
Size: 28(0x1c) bytes
Array: Rank 1, Number of elements 2, Type VALUETYPE
Element Type: System.Drawing.PointF
Fields:
None

0:077> *** Dump contents of the array
0:077> !da 3be693a4 
Name: System.Drawing.PointF[]
MethodTable: 7ae3a114
EEClass: 7adeb1cc
Size: 28(0x1c) bytes
Array: Rank 1, Number of elements 2, Type VALUETYPE
Element Methodtable: 7ae3c3ac
[0] 3be693ac
[1] 3be693b4

现在,您通常需要有关数组中两个对象的更多详细信息。你可以摆弄.foreach 命令,但没有-short 选项,所以使用!mdt 更简单的方法:

0:077> .load D:\debug\Extensions\sosex\4\32\sosex.dll

0:077> !mdt -e:2 3be693a4
3be693a4 (System.Drawing.PointF[], Elements: 2, ElementMT=7ae3c3ac)
[0] (System.Drawing.PointF) VALTYPE (MT=7ae3c3ac, ADDR=3be693ac)
    x:0.000000 (System.Single)
    y:-1.000000 (System.Single)
[1] (System.Drawing.PointF) VALTYPE (MT=7ae3c3ac, ADDR=3be693b4)
    x:1917.000000 (System.Single)
    y:22.000000 (System.Single)
increase depth

更新:PointF 不是最好的例子,因为它也是一个值类型,但它与引用类型类似。

【讨论】:

    猜你喜欢
    • 2017-07-16
    • 2016-05-11
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多