I found that my program leaks at some point, and created full memory dumps (.mdmp) to analyze with WinDbg.
The main cause of memory leak is a strong handle.
0:000> !gcroot 02dc02d4
HandleTable:
000b7000 (strong handle)
-> 114e3174 MyApp.Controls.Forms.TransparentOverlappingForm
-> 114e32b8 System.Windows.Forms.PropertyStore
-> 114e39dc System.Windows.Forms.PropertyStore+ObjectEntry[]
-> 02dc03a4 MyApp.Editor.Main.EditorForm
-> 02dc05cc System.ComponentModel.EventHandlerList
-> 114e3884 System.ComponentModel.EventHandlerList+ListEntry
-> 114bef3c System.ComponentModel.EventHandlerList+ListEntry
-> 114bef28 System.ComponentModel.EventHandlerList+ListEntry
-> 02dc0740 System.ComponentModel.EventHandlerList+ListEntry
-> 02dc0630 System.ComponentModel.EventHandlerList+ListEntry
-> 02dc05fc System.ComponentModel.EventHandlerList+ListEntry
-> 02dc05dc System.EventHandler
-> 02dc02d4 MyApp.Editor.Main.EditorLoad
TransparentOverlappingForm is a form that lays over another control, is used as control, to fully support transparency (this is another story). It is used as such
TransparentOverlappingForm.Show((Control)OverlapsOn);
TransparentOverlappingForm, EditorForm, control that TransparentOverlappingForm overlaps on - all are being closed (if it is a form) and disposed.
There is a leak, just because TransparentOverlappingForm is not being collected, and internally holds a link to EditorForm.
So how to see some info about "000b7000 (strong handle)", to figure out, how can I GC this?
I know that GC strong handle can be a static variable, but how can I figure out is it a static variable, and where is it.
Ah, as always when I ask someone a question, I solve it after this.
I resolved issue in hacky way, there is still small leak, caused by TransparentOverlappingForm.
So the question is open.
var propStoreControlField = typeof(Control).GetField("propertyStore", BindingFlags.Instance | BindingFlags.NonPublic);
var propStoreType = propStoreControlField.FieldType;
var propStoreSetObjectMethod = propStoreType.GetMethod("SetObject", new Type[] {typeof(int), typeof(object)});
var intPropStoreFormField = typeof(Form).GetField("PropDialogOwner", BindingFlags.Static | BindingFlags.NonPublic);
propStoreSetObjectMethod.Invoke(propStoreControlField.GetValue(Form), new object[] {intPropStoreFormField.GetValue(null), null});
Form = null;
OverlapsOn = null;
WinDbg:
0:000> !gcroot 031dcad0
HandleTable:
001f6820 (strong handle)
-> 031dcad0 MyApp.Controls.Forms.TransparentOverlappingForm
Found 1 unique roots (run '!GCRoot -all' to see all roots).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With