Whilst developing POSIX *env API: unleaking portable version, it was necessary to lean on a useful component of the Sun C Compiler. And how – I made plenty of mistakes!
When coding tricksy conditional-deallocation based on tracked pointers where the tracking-array is also in allocated heap memory, and needs to be frequently resized, the possibility of an accidental memory-leak or duplicate-free() is high.
The Sun C Compiler (since version 3.01, approx 1993) comes with a debugger (dbx) capable of automatically detecting these kinds of memory-access/usage mistakes – at runtime.
In particular, even the 1993-vintage dbx detects:
- Deplicate Free – passing the address of an already-freed heap block to free()
- Bad Free – passing the address of a non-heap object to free()
- Read From Unallocated – trying to access through a pointer that does not point to a valid part of the address-space (NULL pointer, wild pointer).
- Read From Unitialised – accessing an object that has not been initialised.
- Write to Unallocated Memory – trying to update through a pointer that does not point to a valid part of the address-space (NULL pointer, wild pointer).
- Heap Memory Leak – there are no (surviving) references to any part of an allocated block.
- Lonely Heap Address in Middle of Block(extremely probable memory leak) – there is no reference to the start of an allocated block, but there is at least one reference to an address within the block.
- Lonely Heap Address in Register (probable memory leak) – an allocated block has not been freed, and no reference to the block exists anywhere in program memory, but a reference exists in a register.
The newer versions of dbx can detect other less-likely errors (mainly misaligned pointers).
These checks can be enabled with the “check -all ; check -access” command in either the GUI-debugger command window or to the command-prompt of the character-mode debugger.
No special alternate libraries or source-code modifications are necessary – just compile with the “debug” flag (-g) and the resulting binary executable can be used both for real runtime production use and for memory-access checking, if desired.