When you embed a managed usercontrol in a Web form, the control may appear to leak memory. The memory leak appears as unclaimed objects in the managed heap when you navigate away from the page or close the browser.
When you perform a Garbage collection in your application, the managed usercontrol's memory resources are not reclaimed. The issue occurs in all up-level browsers on all versions of the .NET framework. The leaks are objects directly allocated in mscorwks.dll. IE ActiveX object activation presents additional challenges that complicate the bookkeeping that IE needs to do. Performing a garbage collection does not release the memory.
This behavior is by design. There is no actual leaked memory. Managed objects that have valid roots cannot be garbage collected. When a managed usercontrol is embedded in a Web form, data is marshalled across two application domains (app domains). The two app domains that are involved are the default Internet Explorer (IE) app domain and the app domain associated with the security zone of the .NET control. Due to marshalling, a reference from the managed usercontrol is passed to the IE app domain. This live remote reference uses .NET remoting to accomplish the marshalling. The marshalled reference has a lease life time associated with it set to 5 minutes by default. Garbage collections performed during this 5 minute interval will not reclaim the reference because it has a valid root. When the time period expires, the resource can be garbage collected.
Due to the nature of those types of applications, the memory issue is not usually critical. If you need to work around this issue, consider lowering the lease life time of the control by calling RemotingServices.Configure to read a remoting configuration file or calling RemoteServices.GetLifetimeService for the remoted object. The call returns an ILease object that may be used to adjust the leased life time setting.
Bear in mind that the lease life time values are carefully chosen; you run the risk of performance issues. Remoting operations will more likely take longer while the control is being used. Every time a call is made into the .NET control, the remote reference will be used resulting in a new reference because the previous one expired too quickly.
Follow these steps to reproduce the problem:
PREPARING THE WEB FORMS
1. Create a physical directory called LeakTest.
2. Create an html file called DynamicLeakTest.html and copy the contents into the file
<html>
<head>
<script type="text/javascript">
var objectTag = null;
function loadControl()
{
if (objectTag == null)
{
objectTag = document.body.appendChild(document.createElement("OBJECT"));
objectTag.id = "emptyUserControl";
objectTag.width = 100;
objectTag.height = 40;
objectTag.border = 1;
objectTag.classid="LeakTestControls/bin/Debug/LeakTestControls.dll#LeakTestControls.EmptyUserControl";
var buttonTag = document.getElementById("loadControlButton");
buttonTag.disabled = true;
buttonTag = document.getElementById("unloadControlButton");
buttonTag.disabled = false;
}
}
function unloadControl()
{
if (objectTag != null)
{
document.body.removeChild(objectTag);
objectTag.clearAttributes();
objectTag.outerHTML = "";
objectTag.outerText = "";
// the following seems to have no effect
delete objectTag;
objectTag = null;
var buttonTag = document.getElementById("loadControlButton");
buttonTag.disabled = false;
buttonTag = document.getElementById("unloadControlButton");
buttonTag.disabled = true;
}
}
function performGarbageCollection()
{
// Perform .NET garbage collection
var garbageCollectorUserControl = document.getElementById("garbageCollectorUserControl");
garbageCollectorUserControl.PerformGarbageCollection();
// Perform JavaScript garbage collection
CollectGarbage();
}
</script>
</head>
<body>
<button id="loadControlButton"
onClick="loadControl()">
Load Control
</button>
<button id="unloadControlButton"
onClick="unloadControl()"
disabled=true>
Unload Control
</button>
<button id="performGarbageCollectionButton"
onClick="performGarbageCollection()">
Perform Garbage Collection
</button>
<br>
<br>
<object id="garbageCollectorUserControl"
classid="LeakTestControls/bin/Debug/LeakTestControls.dll#LeakTestControls.GarbageCollectorControl"
width=0
height=0
hidden=true/>
</body>
</html>
3. Create the usercontrol,EmptyUsercontrol.cs, with code-behind as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace LeakTestControls
{
public partial class EmptyUserControl : UserControl
{
public EmptyUserControl()
{
InitializeComponent();
MessageBox.Show(
"LeakTestControls.EmptyUserControl.EmptyUserControl() has been called.",
"EmptyUserControl",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
System.Diagnostics.Debugger.Break();
}
~EmptyUserControl()
{
MessageBox.Show(
"LeakTestControls.EmptyUserControl.~EmptyUserControl() has been called.",
"EmptyUserControl",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
System.Diagnostics.Debugger.Break();
}
}
}
4. The html file in step 1 references a code-beside file in the function performGarbageCollection(). Add a new file, garbagecollectorcontrol.cs, to the project and copy and paste the following into the file:
using System;
using System.Windows.Forms;
namespace LeakTestControls
{
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterfaceAttribute(System.Runtime.InteropServices.ClassInterfaceType.None)]
public partial class GarbageCollectorControl
: UserControl, IGarbageCollectorControl
{
public GarbageCollectorControl()
{
InitializeComponent();
}
public void PerformGarbageCollection()
{
GC.Collect();
}
}
}
5. Compile the new application.
CONFIGURING THE ENVIRONMENT 1. Make sure you have the .NET 2.0 Framework installed on both the client and web server machines.
2. Set up a virtual directory on your IIS web server that maps to the LeakTest file folder. Make sure its ASP .NET version is set to 2.0.50727 in the properties for the IIS directory.
3. Make sure you have WinDbg installed on the client machine. It can be downloaded from <http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx>. Make sure it is configured to download symbols from microsoft.com by setting the value for the _NT_SYMBOL_PATH environment variable to a value similar to
"srv*C:\MicrosoftPublicSymbols*http://msdl.microsoft.com/download/symbols"
, where "C:\MicrosoftPublicSymbols" is the file folder into which .pdb files will be downloaded. You may already have this set up for a different local path if you already had WinDbg installed. If so then keep using it.
4. Make sure IE6/7 on the client machine is not configured to run a specific version of the .NET Framework other than 2.0. You can do this by examining "C:\Program Files\Internet Explorer\iexplore.exe.config", if it exists and then making sure that there is either no supportedRuntime XML tag or it has been commented out, as shown below:
<configuration>
<runtime><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"></assemblyBinding></runtime>
<startup>
<!-- <supportedRuntime version="v1.1.4322"/> -->
</startup>
<system.windows.forms jitDebugging="true"/>
</configuration>
REPRODUCING THE LEAK1. Launch a new instance of IE6/7 and navigate to DynamicLeakTest.html.
2. Repeat the following two steps for the number of leaked instances you want:
2.1. Click the "Load Control" button.
2.2. Click the "Unload Control" button.
3. Launch WinDbg and attach it to the instance of IE you used for steps 1 and 2. WinDbg will automatically pause the process.
4. Load the Son of Strike extension DLL by typing
".load C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll"
into the command window command prompt and then pressing enter. If all goes well WinDbg will load the DLL without saying anything.
5. Set a breakpoint for automatically pausing WinDbg when generation 2 has been garbage collected by the .NET memory manager (the best time to check for .NET managed memory leaks) by typing the following command as a single line (including both its double-quote characters) into the command window command prompt and then pressing enter:
bp mscorwks!WKS::GCHeap::RestartEE "j(dwo(mscorwks!WKS::GCHeap::GcCondemnedGeneration)==2)'.echo ******** Generation 2 was just collected. ********';'g'"
6. If WinDbg responds with a "Couldn't resolve error at..." error then you probably have the wrong symbol file downloaded for mscorwks.dll. If so then exit WinDbg (which also terminates the IE instance you just started), delete the "mscorwks.pdb" file folder from your symbols subfolder and go back to step 1. You should have to do this only once.
7. Resume the debugger by typing "g" into the command window command prompt and then pressing enter, pressing F5 or clicking the Go toolbar button. It may take significantly longer for this to occur, at least the first time you do this, due to the downloading of symbol files from microsoft.com.
8. Click the "Perform Garbage Collection" button to cause a generation 2 garbage collection and thus pauses WinDbg at a point in time where all objects listed by
should not be live (i.e., should not waiting to be collected by the .NET GC).
9. Issue the command
"!dumpheap -type LeakTestControls.EmptyUserControl"
to list all instances of the control you just leaked. (The "MT" you see in the output of various SOS commands stands for method table. It is typically used as the name for the method table address column in the output of various SOS commands.)
Consider an example that shows 3 instances after clicking the load and then unload buttons 3 times:
0:000> !dumpheap -type LeakTestControls.EmptyUserControl
Address MT Size
02fd4cd4 061305bc 224
02fd62c4 061305bc 224
02fd8210 061305bc 224
total 3 objects
Statistics:
MT Count TotalSize Class Name
061305bc 3 672 LeakTestControls.EmptyUserControl
Total 3 objects
10. Verify that the instances are actually live by using the gcroot command to list what is referencing them:
Consider an example that shows the first instance listed in previous example:
0:000> !gcroot 02fd4cd4
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSTHread 12b4
ESP:13b0b0:Root:02feab58(System.Threading.ExecutionContext)->
02fd2da0(System.Threading.Thread)->
02fdc778(System.Runtime.Remoting.Contexts.Context)->
02fdc5bc(System.AppDomain)->
02fdc620(System.Runtime.Remoting.DomainSpecificRemotingData)->
02feb9a8(System.Runtime.Remoting.Lifetime.LeaseManager)->
02feb9d0(System.Collections.Hashtable)->
02feba08(System.Collections.Hashtable+bucket[])->
02fd50b0(System.Runtime.Remoting.Lifetime.Lease)->
02fd4f18(System.Runtime.Remoting.ObjectHandle)->
02fd4cd4(LeakTestControls.EmptyUserControl)
Scan Thread 12 OSTHread 1390
Scan Thread 13 OSTHread 131c
Scan Thread 16 OSTHread 15f4
Scan Thread 17 OSTHread 1150
DOMAIN(00208568):HANDLE(WeakLn):53610d0:Root:02fd55a4(System.Windows.Forms.NativeMethods+WndProc)->
02fd4dc4(System.Windows.Forms.Control+ControlNativeWindow)->
02fd4cd4(LeakTestControls.EmptyUserControl)
DOMAIN(00208568):HANDLE(Strong):536113c:Root:02fd4f28(System.Runtime.Remoting.ServerIdentity)->
02fd4f18(System.Runtime.Remoting.ObjectHandle)
DOMAIN(00208568):HANDLE(Pinned):53612fc:Root:03fd3250(System.Object[])->
02fdc7fc(System.Collections.Hashtable)->
02fdc834(System.Collections.Hashtable+bucket[])
DOMAIN(00208568):HANDLE(WeakSh):5361330:Root:02fd4dc4(System.Windows.Forms.Control+ControlNativeWindow)->
02fd4f18(System.Runtime.Remoting.ObjectHandle)
DOMAIN(00208568):HANDLE(WeakSh):5361368:Root:02fd4dc4(System.Windows.Forms.Control+ControlNativeWindow)->
02fd4f18(System.Runtime.Remoting.ObjectHandle)
DOMAIN(00208568):HANDLE(RefCnt):53614f4:Root:02fd4cd4(LeakTestControls.EmptyUserControl)->
02fd4f18(System.Runtime.Remoting.ObjectHandle)
DOMAIN(00208568):HANDLE(RefCnt):53614fc:Root:02fd4f18(System.Runtime.Remoting.ObjectHandle)->
02fd4f18(System.Runtime.Remoting.ObjectHandle)
11. You can use the
command to dump the properties of a .NET object.
Dumping the properties of the first control in the example above:
0:000> !do 02fd4cd4
Name: LeakTestControls.EmptyUserControl
MethodTable: 061305bc
EEClass: 060d9ebc
Size: 224(0xe0) bytes
(C:\Documents and Settings\lrhoads1\Local Settings\Application Data\assembly\dl3\8706YH3T.GBY\D9X3B1AH.ETW\2d6493ad\00b31017_f467c701\LeakTestControls.dll)
Fields:
MT Field Offset Type VT Attr Value Name
790f9c18 4000184 4 System.Object 0 instance 00000000 __identity
7a745c0c 40008bc 8 ...ponentModel.ISite 0 instance 02fd53dc site
7a742e54 40008bd c ....EventHandlerList 0 instance 02fd4f08 events
790f9c18 40008bb 108 System.Object 0 static 02fe9b4c EventDisposed
05a4389c 4001107 10 ...ntrolNativeWindow 0 instance 02fd4dc4 window
05495764 4001108 14 ...ows.Forms.Control 0 instance 00000000 parent
05495764 4001109 18 ...ows.Forms.Control 0 instance 00000000 reflectParent
05a44a34 400110a 1c ...orms.CreateParams 0 instance 02fd4e0c createParams
790fed1c 400110b 34 System.Int32 0 instance 0 x
790fed1c 400110c 38 System.Int32 0 instance 0 y
790fed1c 400110d 3c System.Int32 0 instance 0 width
790fed1c 400110e 40 System.Int32 0 instance 0 height
790fed1c 400110f 44 System.Int32 0 instance 0 clientWidth
790fed1c 4001110 48 System.Int32 0 instance 0 clientHeight
790fed1c 4001111 4c System.Int32 0 instance 131085 state
790fed1c 4001112 50 System.Int32 0 instance 3144 state2
054955e4 4001113 54 System.Int32 0 instance 269059 controlStyle
790fed1c 4001114 58 System.Int32 0 instance -1 tabIndex
790fa3e0 4001115 20 System.String 0 instance 00000000 text
790fe8c4 4001116 62 System.Byte 0 instance 0 layoutSuspendCount
790fe8c4 4001117 63 System.Byte 0 instance 0 requiredScaling
0549f414 4001118 24 ...rms.PropertyStore 0 instance 02fd4db4 propertyStore
05a49e20 4001119 28 ...s+TRACKMOUSEEVENT 0 instance 00000000 trackMouseEvent
791052bc 400111a 60 System.Int16 0 instance 0 updateCount
05a497ac 400111b 2c ...s.LayoutEventArgs 0 instance 00000000 cachedLayoutEventArgs
79108964 400111c 30 ...Collections.Queue 0 instance 00000000 threadCallbackList
790fed1c 400111d 5c System.Int32 0 instance 0 uiCuesState
7a742ce4 400108a 184 ...stics.TraceSwitch 0 static 00000000 ControlKeyboardRouting
7a742ce4 400108b 188 ...stics.TraceSwitch 0 static 00000000 PaletteTracing
7a742ce4 400108c 18c ...stics.TraceSwitch 0 static 00000000 FocusTracing
7a742ec8 400108d 190 ...ics.BooleanSwitch 0 static 00000000 BufferPinkRect
790fed1c 400108e 978 System.Int32 0 static 49859 WM_GETCONTROLNAME
790fed1c 400108f 97c System.Int32 0 static 49842 WM_GETCONTROLTYPE
790f9c18 4001090 194 System.Object 0 static 02fe6d30 EventAutoSizeChanged
790f9c18 4001091 198 System.Object 0 static 02fe6d3c EventKeyDown
790f9c18 4001092 19c System.Object 0 static 02fe6d48 EventKeyPress
790f9c18 4001093 1a0 System.Object 0 static 02fe6d54 EventKeyUp
790f9c18 4001094 1a4 System.Object 0 static 02fe6d60 EventMouseDown
790f9c18 4001095 1a8 System.Object 0 static 02fe6d6c EventMouseEnter
790f9c18 4001096 1ac System.Object 0 static 02fe6d78 EventMouseLeave
790f9c18 4001097 1b0 System.Object 0 static 02fe6d84 EventMouseHover
790f9c18 4001098 1b4 System.Object 0 static 02fe6d90 EventMouseMove
790f9c18 4001099 1b8 System.Object 0 static 02fe6d9c EventMouseUp
790f9c18 400109a 1bc System.Object 0 static 02fe6da8 EventMouseWheel
790f9c18 400109b 1c0 System.Object 0 static 02fe6db4 EventClick
790f9c18 400109c 1c4 System.Object 0 static 02fe6dc0 EventClientSize
790f9c18 400109d 1c8 System.Object 0 static 02fe6dcc EventDoubleClick
790f9c18 400109e 1cc System.Object 0 static 02fe6dd8 EventMouseClick
790f9c18 400109f 1d0 System.Object 0 static 02fe6de4 EventMouseDoubleClick
790f9c18 40010a0 1d4 System.Object 0 static 02fe6df0 EventMouseCaptureChanged
790f9c18 40010a1 1d8 System.Object 0 static 02fe6dfc EventMove
790f9c18 40010a2 1dc System.Object 0 static 02fe6e08 EventResize
790f9c18 40010a3 1e0 System.Object 0 static 02fe6e14 EventLayout
790f9c18 40010a4 1e4 System.Object 0 static 02fe6e20 EventGotFocus
790f9c18 40010a5 1e8 System.Object 0 static 02fe6e2c EventLostFocus
790f9c18 40010a6 1ec System.Object 0 static 02fe6e38 EventEnabledChanged
790f9c18 40010a7 1f0 System.Object 0 static 02fe6e44 EventEnter
790f9c18 40010a8 1f4 System.Object 0 static 02fe6e50 EventLeave
790f9c18 40010a9 1f8 System.Object 0 static 02fe6e5c EventHandleCreated
790f9c18 40010aa 1fc System.Object 0 static 02fe6e68 EventHandleDestroyed
790f9c18 40010ab 200 System.Object 0 static 02fe6e74 EventVisibleChanged
790f9c18 40010ac 204 System.Object 0 static 02fe6e80 EventControlAdded
790f9c18 40010ad 208 System.Object 0 static 02fe6e8c EventControlRemoved
790f9c18 40010ae 20c System.Object 0 static 02fe6e98 EventChangeUICues
790f9c18 40010af 210 System.Object 0 static 02fe6ea4 EventSystemColorsChanged
790f9c18 40010b0 214 System.Object 0 static 02fe6eb0 EventValidating
790f9c18 40010b1 218 System.Object 0 static 02fe6ebc EventValidated
790f9c18 40010b2 21c System.Object 0 static 02fe6ec8 EventStyleChanged
790f9c18 40010b3 220 System.Object 0 static 02fe6ed4 EventImeModeChanged
790f9c18 40010b4 224 System.Object 0 static 02fe6ee0 EventHelpRequested
790f9c18 40010b5 228 System.Object 0 static 02fe6eec EventPaint
790f9c18 40010b6 22c System.Object 0 static 02fe6ef8 EventInvalidated
790f9c18 40010b7 230 System.Object 0 static 02fe6f04 EventQueryContinueDrag
790f9c18 40010b8 234 System.Object 0 static 02fe6f10 EventGiveFeedback
790f9c18 40010b9 238 System.Object 0 static 02fe6f1c EventDragEnter
790f9c18 40010ba 23c System.Object 0 static 02fe6f28 EventDragLeave
790f9c18 40010bb 240 System.Object 0 static 02fe6f34 EventDragOver
790f9c18 40010bc 244 System.Object 0 static 02fe6f40 EventDragDrop
790f9c18 40010bd 248 System.Object 0 static 02fe6f4c EventQueryAccessibilityHelp
790f9c18 40010be 24c System.Object 0 static 02fe6f58 EventBackgroundImage
790f9c18 40010bf 250 System.Object 0 static 02fe6f64 EventBackgroundImageLayout
790f9c18 40010c0 254 System.Object 0 static 02fe6f70 EventBindingContext
790f9c18 40010c1 258 System.Object 0 static 02fe6f7c EventBackColor
790f9c18 40010c2 25c System.Object 0 static 02fe6f88 EventParent
790f9c18 40010c3 260 System.Object 0 static 02fe6f94 EventVisible
790f9c18 40010c4 264 System.Object 0 static 02fe6fa0 EventText
790f9c18 40010c5 268 System.Object 0 static 02fe6fac EventTabStop
790f9c18 40010c6 26c System.Object 0 static 02fe6fb8 EventTabIndex
790f9c18 40010c7 270 System.Object 0 static 02fe6fc4 EventSize
790f9c18 40010c8 274 System.Object 0 static 02fe6fd0 EventRightToLeft
790f9c18 40010c9 278 System.Object 0 static 02fe6fdc EventLocation
790f9c18 40010ca 27c System.Object 0 static 02fe6fe8 EventForeColor
790f9c18 40010cb 280 System.Object 0 static 02fe6ff4 EventFont
790f9c18 40010cc 284 System.Object 0 static 02fe7000 EventEnabled
790f9c18 40010cd 288 System.Object 0 static 02fe700c EventDock
790f9c18 40010ce 28c System.Object 0 static 02fe7018 EventCursor
790f9c18 40010cf 290 System.Object 0 static 02fe7024 EventContextMenu
790f9c18 40010d0 294 System.Object 0 static 02fe7030 EventContextMenuStrip
790f9c18 40010d1 298 System.Object 0 static 02fe703c EventCausesValidation
790f9c18 40010d2 29c System.Object 0 static 02fe7048 EventRegionChanged
790f9c18 40010d3 2a0 System.Object 0 static 02fe7054 EventMarginChanged
790f9c18 40010d4 2a4 System.Object 0 static 02fe7060 EventPaddingChanged
790f9c18 40010d5 2a8 System.Object 0 static 02fe706c EventPreviewKeyDown
790fed1c 40010d6 980 System.Int32 0 static 522 mouseWheelMessage
79104f64 40010d7 984 System.Boolean 0 static 0 mouseWheelRoutingNeeded
79104f64 40010d8 988 System.Boolean 0 static 1 mouseWheelInit
790fed1c 40010d9 98c System.Int32 0 static 0 threadCallbackMessage
79104f64 40010da 990 System.Boolean 0 static 0 checkForIllegalCrossThreadCalls
7910fa28 40010db 2ac ...g.ContextCallback 0 static 00000000 invokeMarshaledCallbackHelperDelegate
79104f64 40010dc 0 System.Boolean 0 TLstatic inCrossThreadSafeCall
>> Thread:Value 12b4:0 <<
0549f6f4 40010dd 4 ...ws.Forms.HelpInfo 0 TLstatic currentHelpInfo
>> Thread:Value 12b4:00000000 <<
05a32154 40010de 2b0 ...FontHandleWrapper 0 static 02fea78c defaultFontHandleWrapper
7ae742b0 40010df 2b4 System.Drawing.Font 0 static 02fea694 defaultFont
790fed1c 40010e0 994 System.Int32 0 static 1 PropName
790fed1c 40010e1 998 System.Int32 0 static 2 PropBackBrush
790fed1c 40010e2 99c System.Int32 0 static 3 PropFontHeight
790fed1c 40010e3 9a0 System.Int32 0 static 4 PropCurrentAmbientFont
790fed1c 40010e4 9a4 System.Int32 0 static 5 PropControlsCollection
790fed1c 40010e5 9a8 System.Int32 0 static 6 PropBackColor
790fed1c 40010e6 9ac System.Int32 0 static 7 PropForeColor
790fed1c 40010e7 9b0 System.Int32 0 static 8 PropFont
790fed1c 40010e8 9b4 System.Int32 0 static 9 PropBackgroundImage
790fed1c 40010e9 9b8 System.Int32 0 static 10 PropFontHandleWrapper
790fed1c 40010ea 9bc System.Int32 0 static 11 PropUserData
790fed1c 40010eb 9c0 System.Int32 0 static 12 PropContextMenu
790fed1c 40010ec 9c4 System.Int32 0 static 13 PropCursor
790fed1c 40010ed 9c8 System.Int32 0 static 14 PropRegion
790fed1c 40010ee 9cc System.Int32 0 static 15 PropRightToLeft
790fed1c 40010ef 9d0 System.Int32 0 static 16 PropBindings
790fed1c 40010f0 9d4 System.Int32 0 static 17 PropBindingManager
790fed1c 40010f1 9d8 System.Int32 0 static 18 PropAccessibleDefaultActionDescription
790fed1c 40010f2 9dc System.Int32 0 static 19 PropAccessibleDescription
790fed1c 40010f3 9e0 System.Int32 0 static 20 PropAccessibility
790fed1c 40010f4 9e4 System.Int32 0 static 21 PropNcAccessibility
790fed1c 40010f5 9e8 System.Int32 0 static 22 PropAccessibleName
790fed1c 40010f6 9ec System.Int32 0 static 23 PropAccessibleRole
790fed1c 40010f7 9f0 System.Int32 0 static 24 PropPaintingException
790fed1c 40010f8 9f4 System.Int32 0 static 25 PropActiveXImpl
790fed1c 40010f9 9f8 System.Int32 0 static 26 PropControlVersionInfo
790fed1c 40010fa 9fc System.Int32 0 static 27 PropBackgroundImageLayout
790fed1c 40010fb a00 System.Int32 0 static 28 PropAccessibleHelpProvider
790fed1c 40010fc a04 System.Int32 0 static 29 PropContextMenuStrip
790fed1c 40010fd a08 System.Int32 0 static 30 PropAutoScrollOffset
790fed1c 40010fe a0c System.Int32 0 static 31 PropUseCompatibleTextRendering
790fed1c 40010ff a10 System.Int32 0 static 32 PropImeWmCharsToIgnore
790fed1c 4001100 a14 System.Int32 0 static 33 PropImeMode
790fed1c 4001101 a18 System.Int32 0 static 34 PropDisableImeModeChangedCount
790fed1c 4001102 a1c System.Int32 0 static 35 PropLastCanEnableIme
790fed1c 4001103 a20 System.Int32 0 static 36 PropCacheTextCount
790fed1c 4001104 a24 System.Int32 0 static 37 PropCacheTextField
790fed1c 4001105 a28 System.Int32 0 static 38 PropAmbientPropertiesService
79104f64 4001106 a2c System.Boolean 0 static 1 UseCompatibleTextRenderingDefault
790fe160 400111e a30 System.IntPtr 0 static 0 originalImeContext
00000000 400111f a34 System.Int32 0 static -1 propagatingImeMode
7ae73ae8 40011bd 78 System.Drawing.Size 1 instance 02fd4d4c userAutoScrollMinSize
7ae73cf4 40011be 80 ...Drawing.Rectangle 1 instance 02fd4d54 displayRect
7ae73ae8 40011bf 90 System.Drawing.Size 1 instance 02fd4d64 scrollMargin
7ae73ae8 40011c0 98 System.Drawing.Size 1 instance 02fd4d6c requestedScrollMargin
7ae73e6c 40011c1 a0 System.Drawing.Point 1 instance 02fd4d74 scrollPosition
05a324c4 40011c2 64 ...+DockPaddingEdges 0 instance 00000000 dockPadding
790fed1c 40011c3 70 System.Int32 0 instance 0 scrollState
05a46b6c 40011c4 68 ...VScrollProperties 0 instance 02fd4e68 verticalScroll
05a46c2c 40011c5 6c ...HScrollProperties 0 instance 02fd4e40 horizontalScroll
79104f64 40011c7 74 System.Boolean 0 instance 0 resetRTLHScrollValue
7a742ce4 40011bc 304 ...stics.TraceSwitch 0 static 00000000 AutoScrolling
790f9c18 40011c6 308 System.Object 0 static 02fe6c74 EVENT_SCROLL
05495764 40011ce a8 ...ows.Forms.Control 0 instance 00000000 activeControl
05495764 40011cf ac ...ows.Forms.Control 0 instance 00000000 focusedControl
05495764 40011d0 b0 ...ows.Forms.Control 0 instance 00000000 unvalidatedControl
00000000 40011d1 b8 System.Int32 0 instance -1 autoValidate
7910d61c 40011d2 b4 System.EventHandler 0 instance 00000000 autoValidateChanged
7ae73bf0 40011d3 c0 System.Drawing.SizeF 1 instance 02fd4d94 autoScaleDimensions
7ae73bf0 40011d4 c8 System.Drawing.SizeF 1 instance 02fd4d9c currentAutoScaleDimensions
054986d4 40011d5 bc System.Int32 0 instance 1 autoScaleMode
7a750638 40011d6 d0 ...lized.BitVector32 1 instance 02fd4da4 state
790fed1c 40011d7 aac System.Int32 0 static 1 stateScalingNeededOnLayout
790fed1c 40011d8 ab0 System.Int32 0 static 2 stateValidating
790fed1c 40011d9 ab4 System.Int32 0 static 4 stateProcessingMnemonic
790fed1c 40011da ab8 System.Int32 0 static 8 stateScalingChild
790fed1c 40011db abc System.Int32 0 static 16 stateParentChanged
790fed1c 40011dc ac0 System.Int32 0 static 0 PropAxContainer
0549913c 40039fa d4 System.Int32 0 instance 0 borderStyle
790f9c18 40039f9 1074 System.Object 0 static 02fe6c68 EVENT_LOAD
7a745214 4000001 d8 ...tModel.IContainer 0 instance 02fd4e90 components
12. Exit IE6/7. WinDbg will pause. Examine the .NET heap again as explained above. The EmptyUserControl object instances will still be live on the .NET heap.
For further reading on AppDomains, see this link, http://blogs.msdn.com/jackg/archive/2006/03/10/549046.aspx.
For further reading on Managed Usercontrols, see this link, http://support.microsoft.com/kb/555687
Special thanks to <>, and other members of the <> for his contribution to this article.