The questions it can answer and problems it can solve include:

  • How much memory am I using?
  • Which parts of my code are allocating the most memory?
  • Are there memory leaks - and where am I failing to deallocate?
  • Is a pointer being used after it is deallocated .. or after it has been re-used - and crashing my program?
  • For a given pointer, is it still valid, where was it allocated and how large is the block of memory?
  • Is my program deallocating or freeing invalid pointers?
  • Am I reading or writing beyond the end of an allocation and overwriting memory? If so, where?

Answering these questions solves many unexplained crashes. Ensuring code is clear from the types of issue listed also improves software quality.


The region of memory that the memory debugging mode helps with is known as the heap. The heap is the area managed by the malloc, free and similar functions in C, the new and delete operator in C++, and the allocate and deallocate primitives in F90, and later Fortran derivatives.

DDT intercepts these functions to provide error detection, to record information, and to measure how much memory is being used.

The level of checks is determined by a settings level in the Memory Debugging settings dialog - from basic to full checks. Full mode can slow down codes that perform very large numbers of allocations whereas basic has a usually near-zero time cost.

Memory usage

The total memory usage is an important number to watch. Allocating too much memory results in the operating system killing your process.

The running total for a process is shown on the Tools / Overall Memory Stats menu item. When debugging more than one process, they (or the top N processes by use) display in this view.

This view is available whenever Memory Debugging is enabled: if the total creeps up, then this is an indication of a memory leak.

Arm Forge, the tool suite that includes DDT, also has memory profiling in its MAP performance profiler.  MAP graphically profiles the usage of memory as it varies over time which helps to narrow down when and where memory usage is increasing.

This view is available whenever Memory Debugging is enabled: if the total creeps up, then this is an indication of a memory leak.

Arm Forge, the tool suite that includes DDT, also has memory profiling in its performance profiler, MAP.  MAP graphically profiles the usage of memory as it varies over time - which helps to narrow down when and where memory usage is increasing.

Memory leak detection

If memory is allocated but not deallocated, then this eventually leads to memory exhaustion and abrupt termination.

Memory leaks are detected by using the Tools > Current Memory Usage menu item, which is available whenever Memory Debugging is enabled.

For each memory allocation, DDT records the stack trace and the requested allocation size. This allows it to know where in the code allocations occur, and how much is being used.

The Current Memory Usage dialog uses this information to plot the most commonly calling locations, in terms of bytes used.  If a leak is happening, it shows in this bar chart. Clicking through elements on the bar chart lists the pointers, and selecting a pointer shows the stack and the size of that allocation.

Custom Allocators and Class Constructors

Many codes often channel allocations through a small number of entry points.

For example, the constructor of a C++ class constructor would often be used to allocate memory. The most useful classes can be invoked throughout a program. In these cases, it is more helpful to group allocations by the line of code that called the constructor, so that the calls to the constructor are not lumped together in one unstructured form.

To group by calls to the constructor, right-click in a block in this bar chart to add that represented function as a Custom Allocator. Calls to that function are then grouped separately by call location.

Automating Leak Detection and Regression Testing

DDT has a non-interactive memory debugging mode which replicates the interactive information of the Current Memory Usage tool described above. This mode is often used during overnight tests or in continuous integration servers to measure memory usage and automatically ensure that leaks do not enter production code.

This mode creates an HTML file containing the memory allocations that remain after a process (or processes) terminates.

ddt --offline offline-log.html --mem-debug ... application.exe ....

This creates an annotated log file of the non-interactive debugging session which contains a leak report with the top leaks identified along with significant debugging events that are logged throughout the execution of the program.

Deallocating invalid pointers

Crashes can also occur when trying to deallocate an allocation that has previously been deallocated, or a bogus address (either not allocated, or part way through a legitimate range of heap memory).

This leads to either immediate termination, or heap corruption, and a crash at some future point.

In DDT, this kind of problem is prevented as invalid pointers immediately trigger an error message, and stop the process exactly where the error occurs.

Dangling pointers

Dangling pointers are pointers that have had memory freed but which have not been set to null. It is often possible for subsequent code to keep on using the dangling pointer and to keep on getting valid-looking data until that memory is suddenly repurposed for something else.

This leads to unpredictable behavior, silent corruption and program crashes.

To enable detection of dangling pointers, the memory debugging settings must be set to one level higher than Fast. The term free-protect appears in the Enabled Checks window.

This level of memory debugging is usually all you need to find dangling pointer problems. When a dangling pointer is reused, DDT stops your program at the exact line of code that reuses it, with an error like this one:

The debugger also shows which pointer is dangling and exactly where it was originally allocated. Right-click on any pointers or dynamically-allocated arrays and choose View Pointer Details from the menu:

Arm DDT immediately indicates that this pointer is dangling (it indicates that the pointer points to an allocation that has already been freed) and shows the full stack of function calls that led to its allocation.

Checking pointer information

As described in Dangling pointers, the Pointer Details window provides a lot of information about any pointer:

  • Whether the pointer is valid, not yet allocated or dangling.
  • What size of allocation is or was made.
  • The exact position and stack in the code that the pointer was allocated at, even if it is a dangling pointer that has since been freed.
  • The exact position and stack in the code that the pointer was deallocated again, if it is indeed a dangling pointer.

In particular, the image in Dangling pointers shows that it was allocated at hello.c:88. Clicking on this immediately jumps to that location in the source code viewer. It also indicates where this memory was deallocated.

Reading or writing beyond array bounds or allocation ends

Reading a value from the start or end of the range of an array or other allocation is difficult.

Much of the time, it can go unnoticed, but it can also cause intermittent crashes, where the likelihood of a crash occurring or not depends on the tiniest of changes in runtime environment.

  • Reading a value means polluting a calculation, as the resulting value or code path now depends on something unreliable and uncertain.
  • Writing to such a location can cause uncertain behavior in other areas of the code that then re-use this now corrupted location.
  • Both reading and writing can cause a crash if the address is outside of the program's allocated pages (usually 4096 bytes but some systems use much larger pages).

DDT prevents these kinds of error by working with the operating system to create a page after, or before, each allocation and makes it read and write protected. As soon as the protected memory is touched for a read or write, the Linux O/S notifies the debugger. This is known as Guard Pages, also known as Red Zones.

For codes with a relatively small number of large allocations, such as most scientific codes, and most F90 codes, the number of pages used as guard pages is small.

C++ codes often use significantly many small allocations and can exhaust process limits. For these types of codes DDT, offers an alternative setting known as fence checking or fence painting.  This periodically validates a few bytes above and below an allocation to check for unexpected writes.

Note: This mode only checks writes, it cannot detect erroneous reads, and therefore Guard Pages mode is generally preferred where possible for a code.