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

# Preparation

This page describes the preparations that you need to perform before starting to use libcwd in your applications source code.

### Step 1: Installing libcwd

Binary distributions should be installed the usual way.

If you are installing libcwd from source then please read the INSTALL file that is included in the source distribution.
See also: Configuration Options And Macros

### Step 2: Creating the custom header files

You need to add two custom header files to your application.
The recommended names are "debug.h" and "sys.h".

You can use the following templates for a quick start:

sys.h example template

      // sys.h
      //
      // This header file is included at the top of every source file,
      // before any other header file.
      // It is intended to add defines that are needed globally and
      // to work around Operating System dependend incompatibilities.

      // EXAMPLE: If you use autoconf you can add the following here.
      // #ifdef HAVE_CONFIG_H
      // #include "config.h"
      // #endif

      // EXAMPLE: You could add stuff like this here too
      // (Otherwise add -DCWDEBUG to your CFLAGS).
      // #if defined(WANTSDEBUGGING) && defined(HAVE_LIBCWD_BLAHBLAH)
      // #define CWDEBUG
      // #endif

      // The following is the libcwd related mandatory part.
      // It must be included before any system header file is included!
      #ifdef CWDEBUG
      #ifndef _GNU_SOURCE
      #define _GNU_SOURCE
      #endif
      #include <libcwd/sys.h>
      #endif

  «download»

debug.h example template

      #ifndef DEBUG_H
      #define DEBUG_H

      #ifndef CWDEBUG

      #include <iostream>     // std::cerr
      #include <cstdlib>      // std::exit, EXIT_FAILURE

      #define AllocTag1(p)
      #define AllocTag2(p, desc)
      #define AllocTag_dynamic_description(p, data)
      #define AllocTag(p, data)
      #define Debug(STATEMENT...)
      #define Dout(cntrl, data)
      #define DoutFatal(cntrl, data) LibcwDoutFatal(, , cntrl, data)
      #define ForAllDebugChannels(STATEMENT...)
      #define ForAllDebugObjects(STATEMENT...)
      #define LibcwDebug(dc_namespace, STATEMENT...)
      #define LibcwDout(dc_namespace, d, cntrl, data)
      #define LibcwDoutFatal(dc_namespace, d, cntrl, data) do { ::std::cerr << data << ::std::endl; ::std::exit(EXIT_FAILURE); } while(1)
      #define LibcwdForAllDebugChannels(dc_namespace, STATEMENT...)
      #define LibcwdForAllDebugObjects(dc_namespace, STATEMENT...)
      #define NEW(x) new x
      #define CWDEBUG_ALLOC 0
      #define CWDEBUG_MAGIC 0
      #define CWDEBUG_LOCATION 0
      #define CWDEBUG_LIBBFD 0
      #define CWDEBUG_DEBUG 0
      #define CWDEBUG_DEBUGOUTPUT 0
      #define CWDEBUG_DEBUGM 0
      #define CWDEBUG_DEBUGT 0
      #define CWDEBUG_MARKER 0

      #else // CWDEBUG

      // This must be defined before <libcwd/debug.h> is included and must be the
      // name of the namespace containing your `dc' (Debug Channels) namespace
      // (see below).  You can use any namespace(s) you like, except existing
      // namespaces (like ::, ::std and ::libcwd).
      #define DEBUGCHANNELS ::myproject::debug::channels
      #include <libcwd/debug.h>

      namespace myproject {
        namespace debug {

          void init(void);            // Initialize debugging code from main().
          void init_thread(void);     // Initialize debugging code from new threads.

          namespace channels {        // This is the DEBUGCHANNELS namespace, see above.
            namespace dc {            // 'dc' is defined inside DEBUGCHANNELS.

              using namespace libcwd::channels::dc;
              using libcwd::channel_ct;

              // Add the declaration of new debug channels here
              // and add their definition in a custom debug.cc file.
              extern channel_ct custom;

            } // namespace dc
          } // namespace DEBUGCHANNELS
        }
      }

      #endif // CWDEBUG

      #endif // DEBUG_H

  «download»

This debug.h file is for applications; for more detailed information and for information for library developers who want to use libcwd, please also read The Custom debug.h File.

### Step 3: Creating the custom source file

If you added one or more custom debug channels to your namespace `DEBUGCHANNELS` in your custom "debug.h", then of course you also need to add the definition somewhere. You can do that anywhere, or you could add a special source file for it.

debug.cc example template

      #include "sys.h"
      #include "debug.h"

      #ifdef CWDEBUG

      namespace myproject {           // >
        namespace debug {             //  >--> This part must match DEBUGCHANNELS, see debug.h
          namespace channels {        // >

            namespace dc {

              // Add new debug channels here.
              channel_ct custom("CUSTOM");

            } // namespace dc

          } // namespace DEBUGCHANNELS

      // Initialize debugging code from new threads.
      void init_thread(void)
      {
        // Everything below needs to be repeated at the start of every
        // thread function, because every thread starts in a completely
        // reset state with all debug channels off etc.

      #if LIBCWD_THREAD_SAFE          // For the non-threaded case this is set by the rcfile.
        // Turn on all debug channels by default.
        ForAllDebugChannels(while(!debugChannel.is_on()) debugChannel.on());
        // Turn off specific debug channels.
        Debug(dc::bfd.off());
        Debug(dc::malloc.off());
      #endif

        // Turn on debug output.
        // Only turn on debug output when the environment variable SUPPRESS_DEBUG_OUTPUT is not set.
        Debug(if (getenv("SUPPRESS_DEBUG_OUTPUT") == NULL) libcw_do.on());
      #if LIBCWD_THREAD_SAFE
        Debug(libcw_do.set_ostream(&std::cout, &cout_mutex));

        // Set the thread id in the margin.
        char margin[12];
        sprintf(margin, "%-10lu ", pthread_self());
        Debug(libcw_do.margin().assign(margin, 11));
      #else
        Debug(libcw_do.set_ostream(&std::cout));
      #endif

        // Write a list of all existing debug channels to the default debug device.
        Debug(list_channels_on(libcw_do));
      }

      // Initialize debugging code from main().
      void init(void)
      {
        // You want this, unless you mix streams output with C output.
        // Read  http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#8 for an explanation.
        // We can't use it, because other code uses printf to write to the console.
      #if 0
        Debug(set_invisible_on());
        std::ios::sync_with_stdio(false);     // Cause "memory leaks" ([w]cin, [w]cout and [w]cerr filebuf allocations).
        Debug(set_invisible_off());
      #endif

        // This will warn you when you are using header files that do not belong to the
        // shared libcwd object that you linked with.
        Debug(check_configuration());

      #if CWDEBUG_ALLOC
        // Remove all current (pre- main) allocations from the Allocated Memory Overview.
        libcwd::make_all_allocations_invisible_except(NULL);
      #endif

        Debug(read_rcfile());

        init_thread();
      }

        } // namespace debug
      } // namespace myproject

      #endif // CWDEBUG

  «download»

The above is just an example of course. But if you'd use it, then you would initialize libcwd by including the following at the top of main:

    int main()
    {
    #ifdef CWDEBUG
      myproject::debug::init();
    #endif
    // ...

And every thread would call `myproject::debug::init_thread();` when started.