Looking at arrays with SOS on WinDBG is not exactly the most intuitive process in the world. In order to demonstrate how to do this, I've written a small sample program that I'm going to “debug”. The code simply creates three arrays:
All of the information in this post was done debugging Whidbey, though it should still apply to v1.0 and v1.1 of the runtime. This was also all done on x86. If you're using IA64 or AMD64 then obviously the array format will be slightly different (there will be more padding, and the addresses will be 64 bits instead of 32), but the general format will remain the same, and you should be able to figure out what's going on from looking at memory dumps.
The first step is to get the addresses of these arrays (I'll edit all of my WinDBG outputs to focus on the relevant portions):
In order to look at arrays of native types (here, int and double), just doing a standard !do doesn't provide much information. Working with my integer array:
Instead of using SOS to look at this memory, I'll instead just dump the memory contents at that address:
I've highlighted relevant portions. The first word, in green, is the method table for the type of array. If you do a !dumpmt on this address, you'll see that this is an array of integers:
The second word, in blue, is the number of elements in the array. In this example, there are 7 elements. The next seven words, shown here in maroon, are the actual integers stored in the array. You can see they're hex values 0x15 through 0x1b, which are 21-27 in decimal ... the values in the array
The floating point array works much the same. From the first !dso, remember that the floating point array starts at address 00ac2ad8. Running a !do on this just says that this is an array of doubles:
To get useful information, once again dump the memory at the address:
Again, I've highlighted the relevant portions. The first word, in green, is once again the method table for this array. Dumping that shows we have an array of doubles:
The next word, in blue, is the number of elements in the array. This shows there's only one element. Since a double is 64 bits, the next two words form the value of this element. However, they are currently arranged in little endian format, and they need to be in big endian. To get this value, simply put the second word before the first. The value of this double is therefore: 0x40091eb851eb851f. Since I haven't memorized the IEEE floating point format, and certainly can't just interpret it by sight, I'll use the WinDBG .formats command to translate this value:
You can see that it translates to the expected value of 3.14
Arrays of objects work a little differently. Running a !do on one shows the usual information:
So lets move on to dumping the memory directly, where I'll again highlight the relevant portions:
The first two words should be familiar, the first one is the method table for the type of array, and the second one is the number of elements in the array. The third word, highlighted in purple, is interesting. It's the address of the method table of the type of object contained in the array. Since running a !dumpmt on the first word only shows us that this is an array of objects, we have to do a !dumpmt on the third word to figure out what kind of objects they are:
From the previous method tables, and from looking at the second word, we see we have an array of 3 objects of type System.String. The three words following the type method table address are the addresses of the items stored in the array. You can simply run a !do on these addresses to examine the objects contained within the array (edited for brevity):
From looking at this data, we can see that the three strings are "String 1", "String 2", "String 3".