The. NET Memory Profiler API allows you to automatically detect memory leaks and control the profiler from within the profiled process.
Potential memory leaks are detected by applying assertions to the code that should be tested. There are three ways of applying the assertions:
Using the old-style memory assertions. Click here for an example.
Using the AssertionsDefinition class. Click here for an example.
Using attributes to declaratively define the expected memory usage of a method. Click here for an example.
If the memory assertion fails, a dialog will be shown by the profiler. This dialog will present information about the failed assertion and allow you to decide on actions to perform.
Click the image to magnify.
Memory Assertion Examples
Below are three examples of how memory assertions can be performed. All three examples perform the same memory assertion, with different approaches. Even though the AssertionsDefinition approach is a bit more verbose, it is recommended over the old-style assertions, since it provides much more flexibility and more assertions, like MaxNewInstances, MaxInstances, and MaxNewBytes.
Detect Memory Leaks using the old-style Assertions
The code below shows how memory assertions can be used to detect whether new instances have unintentionally been created by an action. The action in this case is to show a dialog, and that action should not result in any new System. ComponentModel. Component instances.
Void ShowSomeDialog()
{
// Establish a base snapshot
MemProfiler. FastSnapShot();
Using( SomeDialog dlg = new SomeDialog() )
{
dlg. ShowDialog();
}
// Assert that no new Component instances have been
// created. The FastSnapshot collected at the
// beginning of the method will be used as
// reference.
MemAssertion. NoNewInstances( typeof(Component), true );
}
Detect Memory Leaks
using AssertionsDefinition
The code below shows how the AssertionsDefinition class can be used to detect whether new instances have unintentionally been created by an action. The action in this case is to show a dialog, and that action should not result in any new System. ComponentModel. Component instances.
Void ShowSomeDialog()
{
// Establish a base snapshot
MemProfiler. FastSnapShot();
Using( SomeDialog dlg = new SomeDialog() )
{
dlg. ShowDialog();
}
// Assert that no new Component instances have been
// created. The FastSnapshot collected at the
// beginning of the method will be used as
// reference.
using( MemAssertion. BeginAssertions() )
{
AssertionsDefinition ad = new AssertionsDefinition();
ad. NoNewInstances( typeof( Component ), true );
MemAssertion. Assert( ad );
}
}
Detect Memory Leaks using Attributes
The code below shows how an assertion attribute can be used to detect whether new instances have unintentionally been created by a method. In this example we have method that shows a dialog and closes it. After this method has been executed, no new instances of System. ComponentModel. Component should exist. This is declared by applying the NoNewInstances attribute to the method.
[NoNewInstances(typeof( Component ), IncludeSubclasses = true )]
Void ShowSomeDialog()
{
using( SomeDialog dlg = new SomeDialog() )
{
dlg. ShowDialog();
}
}
Unit Testing
It is also possible to use the API together with a unit testing framework, like NUnit. All memory assertion methods return a boolean value, indicating whether the assertion was successful.