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