Hi all,

This post is a continuation of MANAGED DEBUGGING with WINDBG. Managed Heap. Part 1.

 

MANAGED HEAP. Part 2

 

·         We can take a look to the objects in the heap:

We can see all objects in the heap:

0:004> !DumpHeap

 Address       MT     Size

7b463c40 790fd0f0       12    

7b463c4c 790fd8c4       36    

7b463c70 790fd8c4       20    

...   

01905378 79119a1c       32    

...

02907de0 003d6d48       16 Free

total 12400 objects

Statistics:

      MT    Count    TotalSize Class Name

7b492254        1           12 System.Windows.Forms.VisualStyles.VisualStyleRenderer+ThemeHandle

...

79119a1c        3           96 System.Security.Policy.PermissionRequestEvidence

...

003d6d48       11          164      Free

...

790fd0f0      165         1980 System.Object

...

790fd8c4     7308       435252 System.String

Total 12400 objects

0:004> !do 01905378

Name: System.Security.Policy.PermissionRequestEvidence

...

0:004> !do 02907de0

Free Object

Size 16(0x10) bytes

 

Note the existence of Free objects in the heap. The Free entry represents objects which are not referenced and have been garbage collected, but whose memory hasn't been compacted and released to the operating system yet. These regions of space can be re-used by the Garbage Collector later. If 30% or more of the heap contains Free objects, the process may suffer from heap fragmentation.

I’m sure we noticed that there are too many objects in the heap, so it’s usually better to see only the statistics:

0:004> !DumpHeap -stat

total 12400 objects

Statistics:

      MT    Count    TotalSize Class Name

7b492254        1           12 System.Windows.Forms.VisualStyles.VisualStyleRenderer+ThemeHandle

...

79119a1c        3           96 System.Security.Policy.PermissionRequestEvidence

...

003d6d48       11          164      Free

...

790fd0f0      165         1980 System.Object

...

790fd8c4     7308       435252 System.String

Total 12400 objects

 

We can also focus on the objects of a given type only:

0:004> !Name2EE * System.Security.Policy.PermissionRequestEvidence

Module: 790c2000 (mscorlib.dll)

Token: 0x0200048a

MethodTable: 79119a1c

...

0:004> !DumpHeap -mt 79119a1c

 Address       MT     Size

01901ebc 79119a1c       32    

01905378 79119a1c       32    

019290c0 79119a1c       32    

total 3 objects

Statistics:

      MT    Count    TotalSize Class Name

79119a1c        3           96 System.Security.Policy.PermissionRequestEvidence

Total 3 objects                                                                    

 

Or focus on objects of several types with part of the name in common:

0:004> !DumpHeap -type System.Security.Policy

 Address       MT     Size

01901b78 7910ed68       20    

...

01901ebc 79119a1c       32

...

0192971c 79119bf4       16    

total 38 objects

Statistics:

      MT    Count    TotalSize Class Name

791197b0        1           12 System.Security.PolicyManager

7911c924        1           24 System.Security.Policy.Hash

...

79119a1c        3           96 System.Security.Policy.PermissionRequestEvidence

...

790f97c4        3          156 System.Security.Policy.PolicyLevel

Total 38 objects

 

We can see the objects in the Large Object Heap, and we can do it in several ways:

0:004> !EEHeap -GC

Number of GC Heaps: 1

generation 0 starts at 0x01901018

generation 1 starts at 0x0190100c

generation 2 starts at 0x01901000

ephemeral segment allocation context: none

 segment    begin allocated     size

00423878 7b463c40  7b47a744 0x00016b04(92932)

0041d178 7a733370  7a754b98 0x00021828(137256)

003d6600 790d8620  790f7d8c 0x0001f76c(128876)

01900000 01901000  01949ff4 0x00048ff4(298996)

Large object heap starts at 0x02901000

 segment    begin allocated     size

02900000 02901000  02907df0 0x00006df0(28144)

Total Size   0xa787c(686204)

------------------------------

GC Heap Size   0xa787c(686204)

0:004> !DumpHeap 02901000 02907df0

 Address       MT     Size

02901000 003d6d48       16 Free

02901010 7912d8f8     4096    

...

total 15 objects

Statistics:

      MT    Count    TotalSize Class Name

003d6d48        8          128      Free

7912d8f8        7        28016 System.Object[]

Total 15 objects

0:004> !SOS.DumpHeap -min 85000

...

 

Note that there are objects in LOH which size is smaller than 85,000 bytes (?).

We can also see the objects which are ready for finalization, and in general, which objects in our app have a Finalize method:

0:004> !FinalizeQueue

SyncBlocks to be cleaned up: 0

MTA Interfaces to be released: 0

STA Interfaces to be released: 0

----------------------------------

generation 0 has 703 finalizable objects (00457998->00458494)

generation 1 has 0 finalizable objects (00457998->00457998)

generation 2 has 0 finalizable objects (00457998->00457998)

Ready for finalization 0 objects (00458494->00458494)

Statistics:

      MT    Count    TotalSize Class Name

7b492254        1           12 System.Windows.Forms.VisualStyles.VisualStyleRenderer+ThemeHandle

...

7ae77fa8        2           80 System.Drawing.Icon

...

7b485894       59         3776 System.Windows.Forms.Internal.DeviceContext

Total 703 objects

 

0:004> dd 00457998 00458494-4

00457998  01901f10 01905238 01906414 01906428

...

00457b28  019323f8 019324b0 0193296c 01936378

...

00458488  01949468 019494f0 0194959c

 

0:004> !DumpHeap -mt 7ae77fa8   

 Address       MT     Size

0193296c 7ae77fa8       40    

01936378 7ae77fa8       40    

total 2 objects

Statistics:

      MT    Count    TotalSize Class Name

7ae77fa8        2           80 System.Drawing.Icon

Total 2 objects

 

0:004> !do 0193296c

Name: System.Drawing.Icon

...

0:004> !DumpMT -md 7ae77fa8

...

Name: System.Drawing.Icon

...

--------------------------------------

MethodDesc Table

   Entry MethodDesc      JIT Name

...

7ae2070c   7aea3c88   PreJIT System.Drawing.Icon.Finalize()

...

7ae201dc   7aea3c58   PreJIT System.Drawing.Icon.Dispose()

...

 

Look to the way Reflector.exe shows the Dispose and Finalize (destructor) methods of the “Icon” class we saw above, and how Dispose tells the GC to forget about the Finalize method:

public void Dispose()

{

    this.Dispose(true);

    GC.SuppressFinalize(this);

}

 

~Icon()

{

    this.Dispose(false);

}

 

We can get extra information on the following objects registered for finalization: SyncBlocks and RuntimeCallableWrappers (RCWs). Both of these data structures are cached and cleaned up by the Finalizer thread.

0:000> !FinalizeQueue -detail

To be cleaned Com Data

0x4edc1b8  ComPlusWrapper

0x4edc590  ComPlusWrapper

...

0x4e227b8  ComPlusWrapper

SyncBlock to be cleaned up: 6371

MTA interfaces to be released: 0

STA interfaces to be released: 0

...

 

Every time a COM interface pointer enters the CLR, it is wrapped in a RCW. The RCW has a reference count that is incremented every time a COM interface pointer is mapped to it. The System.Runtime.InteropServices.Marshal.ReleaseComObject method decrements the reference count. If the same COM interface is passed more than once from unmanaged to managed code, the reference count on the wrapper is incremented every time and calling ReleaseComObject returns the number of remaining references. When the reference count reaches zero, the runtime releases all its references on the unmanaged COM object. We use this method to free the COM object and the resources it holds.

 

Next post: MANAGED DEBUGGING with WINDBG. Managed Heap. Part 3.

Index: MANAGED DEBUGGING with WINDBG. Introduction and Index.

 

Regards,

 

Alex (Alejandro Campos Magencio)