# 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:

- Memory allocations of 0.

- Memory freed with a NULL or bogus memory pointer.

- Memory freed of a size that does not match the size of memory that was allocated.

- NULL memory lists passed to `AllocMemFromMemLists()` or `FreeMemToMemLists().`

- Cookies on either side of all memory allocations are checked so they are not altered from the time a memory allocation is made to the time the memory is released. A change in the cookies indicates that your program is writing beyond the bounds of allocated memory.

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.