ebmDevMag.com home
ebm Developer's Magazine
links

developer's mag
main page

article
part 1
part 2
part 3
part 4
part 5
part 6
part 7
part 8


7 - Extra Checking

The code only solves some problems. For instance, a random write to memory won't be caught by these routines, while an off by one error will - however, this is often the first sign of a runaway pointer. As well, some other exotic memory conditions are handled:

  • Using data returned by MEM_MALLOC() before initializing it is caught by filling the memory with a known garbage value. This helps prevent useful garbage data left behind from previous use from appearing to be valid.
  • Likewise, MEM_FREE() fills the memory with garbage before freeing it, helping you to catch pointers that are still in use, but pointing to freed memory.
  • MEM_REALLOC() helps with an obscure bug - a pointer points to data, which is then moved when realloc() needs more room. The pointer still points to the old data, which often looks like valid data. To help with this bug, MEM_REALLOC() always moves the data - as well, since allocating and freeing memory also clear the blocks, bad pointer accesses also show up more easily.

Along with the new calls, there are some testing functions:

  int MEM_CHECK_POINTER(void *ptr,int offset);
You can check a pointer with MEM_CHECK_POINTER() - pass it a pointer returned from any debug allocation function and an offset - the return will be whether the byte at that location is part of the block or not (note: if you are writing larger items, like longs, simply adjust the offset value appropriately).
  int MEM_CHECK_BLOCK(void *ptr);
By passing the same pointer to MEM_CHECK_BLOCK(), you can get a flag indicating if the block is safe (no over/under runs). It's still possible to corrupt the block with random data, but a pointer hasn't written over the data block's edges.
  void MEM_VERIFY_MEMORY(void);
This does the same, but checks all blocks in the system. Use it as a sanity check before and after a problem area.
  void MEM_SHOW_MEMORY(void);
This displays a window, showing memory in the debug system. It can be useful to get an idea of what is allocated right now. It is also displayed in the case that not all memory is freed when the program exits. You can see this feature in action in the example program by pressing the 'Damaged malloc() Pointer' button (which doesn't free up its memory), and then quitting.

These routines will let you check memory and pointers at key areas, and help troubleshoot memory access. And lest you think they will affect the production code, they won't - with NDEBUG defined, the code will be optimized away, with nothing left behind. As with ASSERTING(), always put these calls on a separate line, put braces above and below if necessary, and never use them to handle useful side effects.

Previous Section
Next Section

Copyright © 2001-2006 ebmDevMag.com - Legal Notice