.NET Zone is brought to you in partnership with:

Sasha Goldshtein is a Senior Consultant for Sela Group, an Israeli company specializing in training, consulting and outsourcing to local and international customers.Sasha's work is divided across these three primary disciplines. He consults for clients on architecture, development, debugging and performance issues; he actively develops code using the latest bits of technology from Microsoft; and he conducts training classes on a variety of topics, from Windows Internals to .NET Performance. You can read more about Sasha's work and his latest ventures at his blog: http://blogs.microsoft.co.il/blogs/sasha. Sasha writes from Herzliya, Israel. Sasha is a DZone MVB and is not an employee of DZone and has posted 204 posts at DZone. You can read more from them at their website. View Full User Profile

Identifying Specific Reference Type Arrays with SOS

  • submit to reddit

When you’re looking for arrays of a specific type using SOS, you might notice a weird phenomenon. Value type arrays (such as System.Int32[]) will be shown properly regardless of which command you use, but reference type arrays (such as System.String[]) exhibit some weird behavior. Here’s an example:

0:000> !dumpheap -stat
              MT Count TotalSize Class Name
00007ffecf435740     2       304 System.Byte[]
00007ffecf4301c8     2       320 System.Threading.ThreadAbortException
00007ffecf4327d8    11       696 System.Int32[]
00007ffecf42da78     3       720 System.Collections.Generic.Dictionary`2+Entry[[System.Type, mscorlib],[System.Security.Policy.EvidenceTypeDescriptor, mscorlib]][]
00007ffecf430f48     4       766 System.Char[]
00007ffecf4345a8     2      1072 System.Globalization.CultureData
00007ffecf431d70    26      1456 System.RuntimeType
00007ffecf42fc48   162      7428 System.String
00007ffecf4302c0    27     36400 System.Object[]

As you can see, System.Byte[], System.Int32[] and System.Char[] are clearly visible and have distinct method table pointers, but reference type arrays are nowhere to be seen. Let’s take a look at all the System.Object[] instances:

0:000> !dumpheap -mt 00007ffecf4302c0  
         Address               MT     Size
00000079d06518e0 00007ffecf4302c0      176     
00000079d06524f0 00007ffecf4302c0      112     
00000079d0652d88 00007ffecf4302c0       32     
00000079d0652dd0 00007ffecf4302c0      112     
00000079d0653d38 00007ffecf4302c0      112     
00000079d0653de8 00007ffecf4302c0       40     
00000079d0653e10 00007ffecf4302c0       64     
00000079d0653e50 00007ffecf4302c0       40     
00000079d0653e98 00007ffecf4302c0      216     

It looks like they all have the same method table pointer. And indeed, it would make sense because there’s no reason to duplicate methods on reference type arrays. The JITted code is exactly the same. But when you look at the arrays individually, you can easily identify the specific element type:

0:000> !do 00000079d0652dd0 
Name:        System.String[]
MethodTable: 00007ffecf4302c0
EEClass:     00007ffecee6f5f0
Size:        112(0x70) bytes
Array:       Rank 1, Number of elements 10, Type CLASS

And there it is — the debugger’s telling us that this is an array of strings. How does it know, considering that the method table pointer is the same? It looks at the third QWORD of the array object, which is the element type method table:

0:000> dq 00000079d0652dd0 L3
00000079`d0652dd0  00007ffe`cf4302c0 00000000`0000000a
00000079`d0652de0  00007ffe`cf42fc48

0:000> !dumpmt 00007ffe`cf42fc48
EEClass:         00007ffecedc1aa8
Module:          00007ffecedc1000
Name:            System.String

It’s kind of annoying, but you could conceive a way of checking this automatically. For example, if you’re looking for all the arrays of type System.String[], then — assuming you already know the MT for System.String — you could issue the following loop:

.foreach (arr {!dumpheap -mt 00007ffecf4302c0 -short}) { .if (poi( arr +0n16) == 0x00007ffecf42fc48) { !dumparray arr } }

But there’s in fact an easier alternative. It turns out that !dumpheap can actually determine the array type for us, so the preceding loop can be replaced with a simple:

!dumpheap -type System.String[]

And there we have it, a way to display arrays of a specific reference type using SOS.

I am posting short links and updates on Twitter as well as on this blog. You can follow me: @goldshtn

Published at DZone with permission of Sasha Goldshtein, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)