libcwd

Features

End-users of an application don't need to install libcwd.
The use of namespaces prevents name collisions between debug channels of different libraries.
Debug channels and devices can be turned on or off on a per thread basis.
All debug code can be omitted from the executable by not defining a single CWDEBUG macro.
Code using libcwd looks clean and is surveyable as a result of using a few well-defined macros, avoiding the need of disturbing #ifdef CWDEBUG ... #endif constructs.
Debug output is written to an ostream and as such type-safe and customizable as is usual for C++ ostreams.
An arbitrary number of debug channels and debug devices can be created without any penalty in terms of cpu usage.
Full support for all forms of iterative and recursive calls.
Debug output is surveyable as a result of several possibilities to format the output, like a margin string, a marker string, indentation and fixed-width channel labels.  All formatting is thread specific.
Printing the type of arbitrary variables in demangled form.
Printing addresses in source file:line number presentation.
Deallocation pointer validation.
Magic numbers around allocated memory blocks in order to detect buffer overruns.
Printing an overview of current memory allocations, including start address, size, type of allocated object, source file and line number of allocation and a user definable description.
Finding allocation information with only a pointer that points inside an allocated memory block, in logarithmic time.

"Screen shot"

code example
Dout(dc::notice|error_cf, "Hello World");
<- margin -> NOTICE <- marker -> <- indentation ->  Hello World : error string <new-line>
output example
NOTICE  : Entering exec_prog()
SYSTEM  : pipe([3, 4]) = 0
SYSTEM  : pipe([5, 6]) = 0
  child MALLOC  : operator new (size = 24) = <unfinished>
  child BFD     :     Loading debug symbols from /home/carlo/c++/bfd/bfd...  done
SYSTEM  : fork() = 13078 [parent process]
SYSTEM  : close(4) = 0
SYSTEM  : close(6) = 0
  child BFD     :     Loading debug symbols from /home/carlo/c++/libcw/lib/libcwd.so.0 (40013000) ... done
  child BFD     :     Loading debug symbols from /usr/lib/libstdc++-libc6.1-2.so.3 (40057000) ... done
  child BFD     :     Loading debug symbols from /lib/libm.so.6 (4009e000) ... done
  child BFD     :     Loading debug symbols from /lib/libc.so.6 (400ba000) ... done
  child BFD     :     Loading debug symbols from /usr/lib/libbfd-2.9.5.0.14.so (401ad000) ... done
  child BFD     :     Loading debug symbols from /lib/ld-linux.so.2 (40000000) ... done
  child BFD     :     0x40082003 is at (streambuf.cc:211)
  child MALLOC  : <continued> 0x8053a68
SYSTEM  : poll( [ { 3, POLLIN, 0 }, { 5, POLLIN, 0 }, { 7, POLLIN, POLLIN } ], 3, -1) = 1
  child SYSTEM  : fork() = 0 [child process]
  child SYSTEM  : close(3) = 0
  child SYSTEM  : close(5) = 0
  child SYSTEM  : close(1) = 0
  child SYSTEM  : close(2) = 0
  child SYSTEM  : dup2(4, 1) = 1
  child SYSTEM  : dup2(6, 2) = 2
  child SYSTEM  : close(4) = 0
SYSTEM  : poll( [ { 3, POLLIN, POLLIN }, { 5, POLLIN, 0 }, { 7, POLLIN, 0 } ], 3, -1) = 1
SYSTEM  : read(3, "\t", 128) = 1
SYSTEM  : read(3, "libcwd.so.0", 128) = 11
SYSTEM  : read(3, " => ", 128) = 4
SYSTEM  : read(3, "/usr/lib/libcwd.so.0", 128) = 20
SYSTEM  : read(3, " (0x", 128) = 4
SYSTEM  : read(3, "40018000", 128) = 8
SYSTEM  : read(3, ")\n", 128) = 2
NOTICE  : child process stdout: "\tlibcwd.so.0 => /usr/lib/libcwd.so.0 (0x40018000)\n"
code example
template<typename T>
B<T>::~B(void)
{
  Dout(dc::notice, "Calling the destructor of " <<
                   type_info_of(*this).demangled_name() << " (this == " << this << ")");
  libcwd::alloc_ct const* alloc = libcwd::find_alloc(this);
  if (sizeof(*this) != alloc->size())
  {
    Debug( dc::malloc.off() );
    Debug( libcw_do.set_marker(": | ") );
    Dout(dc::notice, "This is a base class of an object starting at " << alloc->start());
    Dout(dc::notice, "The type of the pointer to the allocated object is " <<
                     alloc->type_info().demangled_name());
    Debug( libcw_do.set_marker(": ` ") );
    Dout(dc::notice, "The destructor was called from " << location_ct(builtin_return_address(0)));
    Debug( dc::malloc.on() );
    Debug( libcw_do.set_marker(": ") );
  }
}

(Click here to download/view the complete program.)

output
MALLOC  : operator new (size = 4) = 0x80518a8
NOTICE  : b is 0x80518a8
MALLOC  : operator new (size = 12) = 0x81371f0
NOTICE  : c is 0x81371f0
NOTICE  : Calling the destructor of B<int> (this == 0x80518a8)
MALLOC  : delete 0x80518a8        screenshot.cc:56   B<int>; (sz = 4)  object `b' 
NOTICE  : Calling the destructor of B<B<char> > (this == 0x81371f4)
NOTICE  : | This is a base class of an object starting at 0x81371f0
NOTICE  : | The type of the pointer to the allocated object is C<double, B<char> >*
NOTICE  : ` The destructor was called from screenshot.cc:65
MALLOC  : delete 0x81371f0        screenshot.cc:60   C<double, B<char> >; (sz = 12)  object `c'
Another output example
MALLOC  : malloc(72) = <unfinished>
BFD     :     address 0x402ad017 corresponds to dl-open.c:114
MALLOC  : <continued> 0x81c1330
BFD     : Loading debug info from ./module.so (0x4031f000) ... done (206 symbols)
MALLOC  : malloc(310) = <unfinished>
BFD     :     address 0x40325943 corresponds to module.cc:16
MALLOC  : <continued> 0x81bfb68
MALLOC  : malloc(300) = <unfinished>
BFD     :     address 0x40325490 corresponds to module.cc:7
MALLOC  : <continued> 0x817c490
MALLOC  : Allocated memory: 1518 bytes in 10 blocks.
malloc    0x817c490            module.cc:7    void*; (sz = 300)  Allocated inside static_test_symbol
malloc    0x81bfb68            module.cc:16   void*; (sz = 310)  Allocated inside global_test_symbol
malloc    0x81c1330            dl-open.c:114  <unknown type>; (sz = 72)
malloc    0x81f52a8         dl-version.c:287  <unknown type>; (sz = 96)
malloc    0x804f410            dl-deps.c:495  <unknown type>; (sz = 52)
malloc    0x81c1290          dl-object.c:107  <unknown type>; (sz = 140)
malloc    0x81c0d30          dl-object.c:41   <unknown type>; (sz = 24)
malloc    0x81c05f8          dl-object.c:40   <unknown type>; (sz = 496)
malloc    0x81f5288            dl-load.c:164  <unknown type>; (sz = 12)
malloc    0x81c00a0            dlerror.c:108  <unknown type>; (sz = 16)
NOTICE  : Finished