Investigating behaviour between two points of execution

This tutorial describes how to use watermarks to examine memory allocations between two points in your application’s execution.

This tutorial will cover:

  1. preamble to setup each of the following watermark examples
  2. adding watermarks manually, via the user interface
  3. displaying memory allocations between watermarks
  4. adding watermarks programatically, via the API

This tutorial is for a native application, but the techniques demonstrated in this tutorial apply to all applications, services and IIS regardless of the technology used to create them. 

Example Application

Memory Validator ships with an example application. These can be found in the  following directories in the Memory Validator installation directory:

  • examples\nativeExample

You need to build this project. The easiest thing to do is to build the examples.sln.

Investigating allocations between two watermarks

Now that you have the example project built, we can start collecting memory allocation data from the example project.

We’re going to show several techniques in this tutorial – we’ll break the tutorial into sections.

Preamble

With the preamble we’re going to setup the conditions for the following sections in the tutorial.

  1. Choose the Launch > Applications > Launch Application… option.
    Memory Validator launch applications menu
  2. The Launch dialog is displayed.
    Memory Validator native and .Net launch dialog
  3. Click Browse… next to Application to Launch and choose the executable that is going to launch the process you want to start checking for memory leaks.

    You can also choose a batch file or a powershell script.

    For this tutorial we’re going to start examples\nativeExample\Release10_0_x64\nativeExample_x64.exe.
    Memory Validator native and .Net launch a process to monitor a child process for memory leaks

  4. Click Launch… to start the example project.
  5. The native example executable starts
    Memory Validator native example
  6. From the Allocation menu, choose Watermarks tutorial….
    Memory Validator native example allocations menu watermark tutorials
  7. The watermarks dialog is displayed.
    Memory Validator native example watermarks dialog
    We’re going to use this dialog for the rest of the tutorial.
  8. First, configure how many allocations to make, and what size each allocation should be. For this tutorial set How many to 500,000 and What size to 4,096.

Memory allocated across a transaction

In this section we’re going to show you how to examine memory allocations that happen across a transaction – something where you’d expect all allocations to have been deallocated (or most allocations to have been deallocated, leaving just the intended created objects and no temporary allocations).

We assume that you have completed the Preamble above and have the Watermarks dialog open in native example.

  1. Using the Memory Validator user interface, click the Add Watermark icon on the toolbar, or Add Watermark… on the Managers menu.

    Memory Validator toolbar Add Watermark

    Memory Validator Managers menu, Add Watermark

  2. The Watermark Name dialog is displayed.

    The suggested name for the watermark is created based on the the name of the function at the top of the stack of the current stack trace.

    Memory Validator Watermark Name dialog

    Edit the name to something appropriate then click OK.

    For this tutorial, edit the name to “start”, then click OK.

  3. Using the Watermarks dialog on native example, click Allocate
    Memory Validator native example watermarks dialog allocate
  4. You can see Memory Validator monitoring the memory allocations as native example allocates the memory.
    Memory Validator allocating memory after a watermark
  5. Wait until the memory allocations have been processed by Memory Validator, then add another watermark and name it “middle”.
  6. Using the Watermarks dialog on native example, click Deallocate All
    Memory Validator native example watermarks dialog deallocate all
  7. You can see Memory Validator monitoring the memory deallocations as native example deallocates the memory.
    Memory Validator watermarks deallocating memory
  8. Wait until the memory deallocations have been processed by Memory Validator, then add another watermark and name it “end”.
  9. In a real application “start”, “middle” and “end” could have been wrapped around a database transaction, or the creation of an object in a CAD program.

    For some testing purposes, and for some bug investigations it would be very useful to know what happened between “start” and “middle”, or “start” and “end”.

    Let’s find out!

  10. Go to the Memory tab on Memory Validator’s user interface.
    Memory Validator watermarks Memory tab
    You may notice some errors displayed in red. This is OK – these errors are part of the example application and will be displayed with Memory Validator’s default settings. For this tutorial we can ignore these error messages.
  11. If you look to the left of the errors you will see two controls for Watermarks.

    There are always two default watermarks: the First watermark and the Last watermark. These represent the start of the collected data and the end of the collected data. All watermarks created manually or via the API will fall between the First Watermark and the Last watermark.

  12. Change the First Watermark combo to “start”.
  13. Change the Last Watermark combo to “end”.
  14. Click Refresh.
  15. The display updates to show the memory allocated between “start” and “end” which has not been deallocated.
    Memory Validator memory between watermarks start and end
    The display sort order is descending, so most recent allocations are at the top. We can see two watermarks, “end” and “middle”, a memory allocation in green that is to do with std::vector (owned by the Watermarks dialog) and a Critical Section (owned by Windows, created inside BeginWaitCursor(), it will be cleaned up during application shutdown) and finally the watermark “start”.

    The memory allocation in green indicates that Memory Validator has seen other memory allocations allocated with an identical callstack and those allocations have been deallocated. This isn’t a guarantee that this location doesn’t leak memory, but it’s a hint that this location may not leak memory.

    So where are the 500,000 allocations? They aren’t displayed between the watermarks because they no longer exist – they were deallocated.

Inspecting memory allocations during a transaction

In this section we’re going to show you how to examine memory allocations part way through a transaction, before the objects get deallocated.

We assume that you have completed the Preamble above and have the Watermarks dialog open in native example. 

You can continue on from the previous tutorial without restarting.

  1. Using the Memory Validator user interface, add a watermark named “before”. 
  2. Using the Watermarks dialog on native example, click Allocate
  3. You can see Memory Validator monitoring the memory allocations as native example allocates the memory.
  4. Wait until the memory allocations have been processed by Memory Validator, then add another watermark and name it “after”.
  5. Let’s investigate the allocations between “before” and “after”.
  6. Go to the Memory tab on Memory Validator’s user interface.
  7. Change the First Watermark combo to “before”.
  8. Change the Last Watermark combo to “after”.
  9. Click Refresh.
  10. The display updates to show the memory allocated between “before” and “after” which has not been deallocated. Memory Validator displaying memory between watermarks before and after.

    The display sort order is descending, so most recent allocations are at the top. We can see watermark “after”, a memory allocation in green that represents 500,000 memory allocations that have an identical callstack, and the watermark “before”.

    The memory allocation in green indicates that Memory Validator has seen other memory allocations allocated with an identical callstack and those allocations have been deallocated. This isn’t a guarantee that this location doesn’t leak memory, but it’s a hint that this location may not leak memory.

    The 500,000 memory allocations are displayed between the two watermarks, but occupy just one entry in the list because of Memory Validator’s display settings are set to “Simplified”.

  11. To display all memory allocations between the watermarks you need to modify the display settings. Click Display…
    Memory Validator memory tab display button
  12. The Memory Tab Display Settings dialog is displayed.
    Memory Validator display tab settings dialog
  13. Change the Callstack grouping combo to Full – show every callstack.
    Memory Validator display tab settings dialog full
    Click OK.
  14. Click Refresh to update the display using the new display preferences.
  15. The display updates to show all allocations with a unique entry for each allocation.
    Memory Validator memory between watermarks before and after

    This is slower to display than the Simplified display and uses more memory.

    For most use cases the Simplified display is preferable to the Full display, but for some bugs where you need to know the exact details of each allocation the Full display is the way to go.

    Memory Validator can display up to 4 billion (4,294,967,295) allocations in this display – limited only by available memory in your computer (and your patience while populating that display!).

  16. Using the Watermarks dialog on native example, click Deallocate All.
    Memory Validator native example watermarks dialog deallocate all
  17. You can see Memory Validator monitoring the memory deallocations as native example deallocates the memory.

    Wait until the memory deallocations have been processed by Memory Validator.

  18. You will also notice that the memory allocations displayed on the Memory tab do not go away despite being deallocated.

    This is because Memory Validator knows you are inspecting them on the Memory tab.

    If you refresh the display it will not show these deallocated memory allocations.

  19. Click Refresh
  20. The Memory tab updates, showing no allocations between watermark “before” and watermark “after”.
    Memory Validator memory between watermarks before and after deallocated

Adding watermarks programmatically via the API

In this section we’re going to show you how to examine memory allocations part way through a transaction, before the objects get deallocated, with watermarks added via the API.

We assume that you have completed the Preamble above and have the Watermarks dialog open in native example. 

You can continue on from the previous tutorial without restarting.

  1. We need to change the display back to showing one callstack for many identical entries – to simplify the display to make it easier to read.

    On Memory Validator’s Memory tab, click Display… to display the Memory Tab Display Settings dialog.

    Change the Callstack grouping combo to Simplified and click OK.
    Memory Validator memory tab display settings callstack grouping simplified

  2. On the Watermarks dialog on native example, select the Add Watermarks via the API check box.
    Memory Validator native example watermarks dialog add watermarks via API
  3. Allocate some memory: click Allocate
  4. Watermarks will be added by native example before the memory allocations, and after the memory allocations. In this example these watermarks added via the API have the names beforeAlloc_n and afterAlloc_n where n is a number that increases each time the Allocate button is clicked.

    The method for adding the watermark via the API is described in the Memory Validator help.

  5. You can see Memory Validator monitoring the memory allocations as native example allocates the memory.
  6. Let’s investigate the allocations between “beforeAlloc_4” and “afterAlloc_4”. The numbers for your example may be different depending on what you’ve done with the dialog during the tutorial.
  7. Go to the Memory tab on Memory Validator’s user interface.
  8. Change the First Watermark combo to “beforeAlloc_4”.
  9. Change the Last Watermark combo to “afterAlloc_4”.
  10. Click Refresh.
  11. The display updates to show the memory allocated between “beforeAlloc_4” and “afterAlloc_4” which has not been deallocated.
    Memory Validator memory tab displaying memory allocations between watermarks added by API

    The display sort order is descending, so most recent allocations are at the top. We can see watermark “afterAlloc_4”, a memory allocation in green that represents 500,000 memory allocations that have an identical callstack, and the watermark “beforeAlloc_4”.

    The memory allocation in green indicates that Memory Validator has seen other memory allocations allocated with an identical callstack and those allocations have been deallocated. This isn’t a guarantee that this location doesn’t leak memory, but it’s a hint that this location may not leak memory.

    The 500,000 memory allocations are displayed between the two watermarks, but occupy just one entry in the list because of Memory Validator’s display settings are set to “Simplified”.

  12. Using the Watermarks dialog on native example, click Deallocate All
    Memory Validator native example watermarks dialog deallocate all
  13. You can see Memory Validator monitoring the memory deallocations as native example deallocates the memory.
  14. You will also notice that the memory allocations displayed on the Memory tab do not go away despite being deallocated.

    This is because Memory Validator knows you are inspecting them on the Memory tab.

    If you refresh the display it will not show these deallocated memory allocations.

  15. Click Refresh
  16. The Memory tab updates, showing no allocations between watermark “beforeAlloc_4” and watermark “afterAlloc_4”.
    Memory Validator displaying memory between watermarks beforeAlloc_4 and afterAlloc_4

Conclusion

You have learned how to use watermarks to inspect memory between two watermarks, to inspect memory during a transaction and across a transaction.

You have also learned how to use watermarks created by using the Memory Validator API.

Fully functional, free for 30 days