libcwd: The C++ Debugging Support Library - Features
Author: Carlo Wood

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 " <<
                       libcwd::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.push_marker());
        Debug(libcw_do.marker().assign(": | "));
        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.marker().assign(": ` "));
        Dout(dc::notice, "The destructor was called from " << location_ct(builtin_return_address(0)));
        Debug(dc::malloc.on());
        Debug(libcw_do.pop_marker());
      }
    }

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

##### output

    MALLOC  : operator new (size = 4) = 0x80584d0 [screenshot.cc:56]
    NOTICE  : b is 0x80584d0
    MALLOC  : operator new (size = 12) = 0x8100fa0 [screenshot.cc:60]
    NOTICE  : c is 0x8100fa0
    NOTICE  : Calling the destructor of B<int> (this == 0x80584d0)
    MALLOC  : delete 0x80584d0        screenshot.cc:56   B<int>; (sz = 4)  object `b'
    NOTICE  : Calling the destructor of B<B<char> > (this == 0x8100fa4)
    NOTICE  : | This is a base class of an object starting at 0x8100fa0
    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 0x8100fa0        screenshot.cc:60   C<double, B<char> >; (sz = 12)  object `c'

##### Another output example

    MALLOC  : malloc(10) = <unfinished>
    WARNING :     Object file /lib/ld-linux.so.2 does not have debug info.  Address lookups inside this object file will result in a function name only, not a source file location.
    MALLOC  : <continued> 0x8125978 [ld-linux.so.2:open_path]
    MALLOC  : calloc(586, 1) = 0x8124f10 [ld-linux.so.2:_dl_new_object]
    MALLOC  : realloc(0x0, 138) = 0x8125170 [ld-linux.so.2:_dl_new_object]
    MALLOC  : malloc(52) = 0x8110fa0 [ld-linux.so.2:_dl_map_object_deps]
    MALLOC  : calloc(8, 16) = 0x8052c98 [ld-linux.so.2:_dl_check_map_versions]
    MALLOC  : malloc(68) = <unfinished>
    WARNING :     Object file /lib/tls/libc.so.6 does not have debug info.  Address lookups inside this object file will result in a function name only, not a source file location.
    MALLOC  : <continued> 0x80569e0 [libc.so.6:dl_open_worker]
    BFD     : Loading debug symbols from module.so (0x40424000) ... done (179 symbols)
    MALLOC  : malloc(310) = <unfinished>
    BFD     :     Loading debug info from module.so... done
    BFD     :     address 0x4042bc90 corresponds to module.cc:24
    MALLOC  : <continued> 0x81ab7b0 [module.cc:24]
    MALLOC  : malloc(300) = <unfinished>
    BFD     :     address 0x4042ba86 corresponds to module.cc:13
    MALLOC  : <continued> 0x81ab8f8 [module.cc:13]
    MALLOC  : Allocated memory: 1592 bytes in 8 blocks.
    malloc    0x81ab8f8            module.cc:13   void*; (sz = 300)  Allocated inside static_test_symbol
    malloc    0x81ab7b0            module.cc:24   void*; (sz = 310)  Allocated inside global_test_symbol
    malloc    0x80569e0 dl_open_worker            <unknown type>; (sz = 68)
    malloc    0x8052c98 _dl_check_map_versions    <unknown type>; (sz = 128)
    malloc    0x8110fa0 _dl_map_object_deps       <unknown type>; (sz = 52)
    realloc   0x8125170 _dl_new_object            <unknown type>; (sz = 138)
    malloc    0x8124f10 _dl_new_object            <unknown type>; (sz = 586)
    malloc    0x8125978 open_path                 <unknown type>; (sz = 10)
    MALLOC  : free(0x81ab7b0)            module.cc:24   void*; (sz = 310)  Allocated inside global_test_symbol
    MALLOC  : free(0x81ab8f8)            module.cc:13   void*; (sz = 300)  Allocated inside static_test_symbol
    MALLOC  : free(0x8052c98) _dl_check_map_versions    <unknown type>; (sz = 128)
    MALLOC  : free(0x8125170) _dl_new_object            <unknown type>; (sz = 138)
    MALLOC  : free(0x8125978) open_path                 <unknown type>; (sz = 10)
    MALLOC  : Trying to free NULL - ignored.
    MALLOC  : Trying to free NULL - ignored.
    MALLOC  : free(0x8124f10) _dl_new_object            <unknown type>; (sz = 586)
    MALLOC  : free(0x8110fa0) _dl_map_object_deps       <unknown type>; (sz = 52)
    NOTICE  : Finished