dotMemory 2024.3 Help

Automatic Inspections

dotMemory can automatically analyze snapshots and detect a number of memory issues.

String duplicates

Repeatedly creating strings with the same value instead of reusing the existing one wastes memory. dotMemory detects duplicated strings and shows how much memory is wasted.

To analyze the objects

  • Click the link in the inspection header or double-click a particular object set in the list.

To fix the issue

  • If strings with the same value waste a huge amount of memory or generate significant traffic (for example, if your app parses text input) consider implementing string interning.

Sparse arrays

Sparse arrays are arrays that are mostly filled with zero elements. Sparse arrays are inefficient from the perspective of performance and memory usage. dotMemory automatically finds sparse arrays and shows you how much memory is lost (occupied by zero values) because of them.

To analyze sparse arrays

  • Click the link in the inspection header or double-click a particular object in the list.

Finalizable objects

Finalizable objects are the objects that use the Finalize() method to release unmanaged resources. The problem of using this pattern is, first, that the lifetime of finalizable objects is extended by at least one more GC cycle and, second, that the finalization thread (that executes the Finalize() method) is run unpredictably. This may cause problems in case you want to reclaim the released resources as quickly as possible and may lead to sudden performance drops. dotMemory detects and shows all objects queued for finalization and objects finalized since the previous snapshot.

To analyze finalizable objects

  1. Click the link in the inspection header or double-click any type in the list.

  2. To leave only types that implement IDisposable, type #d in the Filter field. Note that all disposable types are marked with the Disposable icon.

  3. To leave only types that do not implement IDisposable, type !d in the Filter field.

To fix the issue

  • Implement the IDisposable interface for the type that causes issues and release all unmanaged resources via its Dispose() method. For more information about the dispose pattern, refer to Microsoft Learn.

Event handlers leak

Such a leak occurs when you subscribe an object (let's call it listener) to an event of some other object (let's call it source). For example: Timer1.Tick += OnTimer; During subscription, the source object gets a reference to the event handler of the listener object. If you delete the listener, this reference will prevent it from being garbage collected. dotMemory automatically finds objects that are referenced in event handlers but are never unsubscribed from corresponding events.

To analyze the objects

  • Click the link in the inspection header or double-click a particular object in the list.

To fix the issue

  • Unsubscribe the listener from the event when it is no longer needed. For example: Timer1.Tick -= OnTimer;

WPF binding leak

Breaking WPF data binding patterns also can cause a memory leak. After you perform data binding to some property of a source object, the binding target object starts to listen for property change notifications. If the property is not a DependencyProperty object and the target object doesn't implement the INotifyPropertyChanged interface, a memory leak in the source object and in every object to which the source object refers may occur. dotMemory detects such binding pattern violations and shows you the list of objects that may potentially cause this leak type.

To analyze the objects

  • Click the link in the inspection header or double-click a particular object in the list.

To fix the issue

  • Make the source object implement the INotifyPropertyChanged interface or remove binding when it is no longer needed using the ClearBinding method.

WPF collection binding leak

This leak is similar to the WPF binding leak described above. If there is binding to a collection, that doesn't implement the INotifyCollectionChanged interface, WPF creates a strong reference to this collection. As a result, it stays in memory for the entire application lifetime. dotMemory detects and shows you such objects.

To analyze the objects

  • Click the link in the inspection header or double-click a particular object in the list.

To fix the issue

  • Make the source collection implement the INotifyCollectionChanged interface. Another way is to use the ObservableCollection collection as it already implements the INotifyCollectionChanged interface.

Dependency property leak

Such leaks occur due to the same reasons as the event handlers leak. Garbage Collector will not collect objects subscribed on DependencyProperty changes through the AddValueChanged method until they're unsubscribed using the RemoveValueChanged method. dotMemory detects and shows you all such objects.

To analyze the objects

  • Click the link in the inspection header or double-click a particular object in the list.

To fix the issue

  • When the lifetime of a subscribed object is over, take care of unsubscribing it using the RemoveValueChanged method.

x:Name WPF leak

Such leaks take place because of the following WPF peculiarity: WPF creates a strong global reference to the UI element that is declared in XAML and uses the x:Name directive. For example:

<XNameTest:UserControl1 Grid.Row="0" x:Name="myControl1"/>

Thus, if you dynamically remove the element declared in such a way, it will still be in memory.

To analyze the objects

  • Click the link in the inspection header or double-click a particular object in the list.

To fix the issue

  • One way to remove the leak is to declare the UI element in the C# code instead of XAML. Another way is to call the UnregisterName method of the parent control when you want to remove the UI element. For example: this.UnregisterName("myControl1");

Last modified: 24 July 2024