Debugging Memory Usage


Problems can occur when your application allocates or manages memory if the memory is misused or isn't freed up after use. A memory debugging module is provided to help spot memory management problems. The module replaces the memory allocation routines in your program with a superset that checks that the memory system is used correctly. These calls are activated when you do the following:

  1. Add CreateMemDebug() as the first instruction in the main() routine of your program:

    Err CreateMemDebug(uint32 controlFlags, const TagArg *args);

    controlFlags is a set of bit flags that control various options of the memory debugging code; args is a pointer to an array of tag arguments containing extra data for this function. See the Kernel Folio Calls in the 3DO System Programmer's Reference for a description of each flag. Currently, args must always be NULL.

  2. Add DumpMemDebug() and DeleteMemDebug() as the last instructions in the main() routine of your program.

    Err DumpMemDebug(const TagArg *args);
    Err DeleteMemDebug(void);

    args is a pointer to an array of tag arguments containing extra data for this function. Currently args must always be NULL.

  3. Recompile your entire application with MEMDEBUG defined on the ARM compiler's command line. For the ARM compiler, this is done by adding

    -DMEMDEBUG

    to the compile line.

  4. Link your code with memdebug.lib

    A link order is important when using memdebug.lib. The memdebug library should come before clib.lib, but after everything else. That is, the link order should be:

    [many .lib files] memdebug.lib clib.lib
Other than CreateMemDebug(), DumpMemDebug(), and DeleteMemDebug(), there is no difference in the way your code works. When your program allocates memory, each memory allocation is tracked and managed. In addition, the memory debugging module makes sure that illegal or dangerous memory use is detected and flagged. When your program exits, any memory left allocated is displayed, along with the line number and source file from where memory was allocated.

When all the control flags are turned on, the debugging code checks and reports the following problems:

When MEMDEBUG is defined during compilation, all standard memory allocation calls are automatically vectored through the debugging code. This includes memory allocation calls made in previously compiled .lib files with which you might be linking. However, you can get better debugging information if you recompile everything in your project, including .lib files, with MEMDEBUG defined.

If you call DumpMemDebug() at any time within your application, you can get a detailed listing of all memory currently allocated, showing the source line and source file from which the allocation occurred. This function also outputs statistics about general memory allocation patterns including: the number of memory allocation calls that have been performed, the maximum number of bytes allocated at any one time, current amount of allocated memory, and so on. All of this information is displayed on a per-thread basis, as well as globally for all threads. When using link libraries that haven't been recompiled with MEMDEBUG defined, the memory debugging subsystem will still can track the allocations, but will not report the source file or line number where the error occurred. It reports <unknown source file> instead.

An additional call, SanityCheckMemDebug(), can find problems with memory. This call checks outstanding memory allocations and checks all cookies to see if they have been corrupted. For example, if you want to find the location of a chunk of memory is being corrupted, you could place SanityCheckMemDebug() calls throughout the program. Look at the return data of each call until you locate the place in the program where the cookies are corrupted.

After you finish using any of these calls, turn off memory debugging before you create the final version of your program. Enabling memory debugging incurs an overhead of 32 bytes per allocation made. If you use the MEMDEBUGF_PAD_COOKIES option, this overhead grows to 64 bytes per allocation.