libcwd: The C++ Debugging Support Library - Reference Manual
Author: Carlo Wood
Description: C++ debugging support library with ostream debug output
Keywords: libcwd, debug output, debug facility, debug channel, object orientation, OO, C++, nested debug output, ostream, memory allocation, debugging, source file and line number

Main Page Reference Manual Namespace List Compound List Namespace Members Compound Members File Members

# Overflow/Underflow Protection (Red Zones)
[Memory Allocation Debug Support]

Collaboration diagram for Overflow/Underflow Protection (Red Zones):

Memory corruption bugs are usually very hard to find because they often lead to a program crash in a source line far from the point of the actual bug. Buffer overruns are an important reason for memory corruption. Libcwd tries to help with finding buffer overruns by means of so called magic numbers.

When --enable-magic (CWDEBUG_MAGIC) is defined, magic numbers are added to the beginning and the end of each allocated memory block. In addition to these two magic numbers, extra memory is allocated to hold the allocated size, this is necessary to find back the location of the magic number at the end with only a pointer to the beginning of the allocated memory block. The total size of actually allocated memory is therefore larger than was requested. The size of each field is equal to the size of a `size_t`. Moreover, a few bytes might be allocated extra just in front of the last magic number in order to word align this number.

`new` and `malloc` etc. return a pointer just beyond this size field, see figure 1.

Figure 1. Memory layout of an allocated memory block with `CWDEBUG_MAGIC` set.

The magic numbers are checked when the memory is freed again. Libcwd uses twelve different magic numbers for six pairs, existing each of a start magic number and an end magic number. The six pairs consist of two groups: for memory allocated by the user and for memory allocated internally by libcwd as part of the debug malloc code itself. Thus, each group consists of three pairs: for memory allocated with `malloc`, `operator new` and `operator new[]` respectively.

For example, the following code snippet:

    int* p = new int[4];
    AllocTag(p, "Test array");

    Debug( list_allocations_on(libcw_do) );

    p[4] = 5;       // Buffer overflow
    delete[] p;

results in output like

    MALLOC  : operator new[] (size = 16) = 0x8116460

    MALLOC  : Allocated memory: 16 bytes in 1 blocks.
    new[]     0x8116460         magic_tst.cc:174  int [4]; (sz = 16)  Test array

    MALLOC  : delete[] 0x8116460         magic_tst.cc:174  int [4]; (sz = 16)  Test array <unfinished>
    COREDUMP:     delete[]: magic number corrupt!
    Quit (core dumped)