dbg Namespace Reference

dbg library More...

## Classes

struct | source_pos
| Data structure describing a position in the source file. More...
struct | dbg_exception
| The base type of exception thrown by dbg assertions (and other dbg library constraint checks) if the assertion_behaviour is set to assertions_throw. More...
struct | assertion_exception
| The type of exception thrown by assertion. More...
struct | sentinel_exception
| The type of exception thrown by sentinel. More...
struct | unimplemented_exception
| The type of exception thrown by unimplemented. More...
struct | check_ptr_exception
| The type of exception thrown by check_ptr. More...
class | null_stream
| In non-debug versions, this class is used to replace an ostream so that code will compile away. More...
struct | prefix
struct | indent
class | trace
class | post_mem_fun
class | post
class | compile_assertion

## Typedefs

typedef const char * | dbg_source
| typedef for a string that describes the "source" of a diagnostic. More...
typedef const unsigned int | line_no_t
| Typedef used in the source_pos data structure. More...
typedef const char * | func_name_t
| Typedef used in the source_pos data structure. More...
typedef const char * | file_name_t
| Typedef used in the source_pos data structure. More...
typedef std::clock_t | dbgclock_t
| The dbgclock_t typedef is an unfortunate workaround for comptability purposes. More...

## Enumerations

enum | level { info, warning, error, fatal, tracing, debug, none, all }
| The various predefined debugging levels. More...
enum | assertion_behaviour { assertions_abort, assertions_throw, assertions_continue }
| This enum type describes what happens when a debugging assertion fails. More...

## Functions

void | enable (level, bool)
void | enable (level, dbg_source, bool)
void | enable_all (level, bool)
null_stream | out (level, dbg_source)
null_stream | out (level)
void | attach_ostream (level, std::ostream &)
void | attach_ostream (level, dbg_source, std::ostream &)
void | detach_ostream (level, std::ostream &)
void | detach_ostream (level, dbg_source, std::ostream &)
void | detach_all_ostreams (level)
void | detach_all_ostreams (level, dbg_source)
null_stream | info_out ()
null_stream | warning_out ()
null_stream | error_out ()
null_stream | fatal_out ()
null_stream | trace_out ()
void | set_prefix (const char *)
void | enable_level_prefix (bool)
void | enable_time_prefix (bool)
void | set_assertion_behaviour (level, assertion_behaviour)
void | set_assertion_period (dbgclock_t)
void | assertion (level, dbg_source, void *)
void | assertion (level, void *)
void | assertion (dbg_source, void *)
void | assertion (void *)
void | sentinel (level, dbg_source, void *)
void | sentinel (level, void *)
void | sentinel (dbg_source, void *)
void | sentinel (void *)
void | unimplemented (level, dbg_source, void *)
void | unimplemented (level, void *)
void | unimplemented (dbg_source, void *)
void | unimplemented (void *)
void | check_ptr (level, dbg_source, const void *, void *)
void | check_ptr (level, const void *, void *)
void | check_ptr (dbg_source, const void *, void *)
void | check_ptr (const void *, void *)
void | check_bounds (level, void *, int, int, void *)
void | check_bounds (level, dbg_source, int, void *, void *)
void | check_bounds (level, dbg_source, int, int, void *, void *)
void | check_bounds (level, int, void *, void *)
void | check_bounds (void *, int, void *, void *)
void | check_bounds (int, void *, void *)

## Variables

const int | version = 110
| This is the version number of the dbg library. More...
const dbg_source | default_source = 0

## Detailed Description

dbg library

The dbg library is a set of C++ utilities to facilitate modern debugging idioms.

It has been designed to support defensive programming techniques in modern C++ code. It integrates well with standard library usage and has been carefully designed to be easy to write, easy to read and very easy to use.

It provides various constraint checking utilities together with an integrated error logging facility. These utilities are flexible and customisable. They can be enabled and disabled at runtime, and in release builds, dbg library use can be compiled away to nothing.

Rich debugging can only be implemented in large code bases from the outset, it is hard to retrofit full defensive programming techniques onto existant code. For this reason it is good practice to use a library like dbg when you start a new project. By using dbg extensively you will find bugs quicker, and prevent more insideous problems rearing their head later in the project's life.

For instructions on the dbg library's use see the dbg namespace documentation. The dbg namespace holds a number of C++ debugging utilities.

They allow you to include constraint checking in your code, and provide an integrated advanced stream-based logging facility.

The characteristics of this library are:

- Easy to use (not overly complex) (easy to write, easy to read, easy to use)
- Powerful
- Configurable
- No run time overhead when "compiled out"
- Minimises use of the proprocessor
- Can throw exceptions if required
- Can separate different "sources" of diagnostic output (these sources are differentated by name)
- Designed to be a "standard" library (integrates with the style of the C++ standard library and works well with it)

Enabling debugging

To use dbg in your program you must `#include <dbg.h>` and compile with the `DBG_ENABLED` flag set.

If you build without DBG_ENABLED you will have no debugging support (neither constraints nor logging). There is no overhead building a program using these utilities when DBG_ENABLED is not set. Well, actually there might be minimal overhead: there is no overhead when using gcc with a little optimisation (`-O3`). There is a few bytes overhead with optimisation disabled. (The `-O1` level leaves almost no overhead.)

Either way, the rich debugging support is probably worth a few bytes.

Once your program is running, you will want to enable diagnostic levels with dbg::enable, and probably attach an ostream (perhaps `cerr`) to the diagnostic outputs. See the default states section below for information on the initial state of dbg.

Aside: The standard `assert` macro is an insideous little devil, a lower case macro. This library replaces it and builds much richer constraints in its place. However, because of it, we have to use an API name dbg::assertion, not dbg::assert - this makes me really cross, but I can't assume that the user does not `#include <assert.h>` when using `<dbg.h>` .

Using constraints

The dbg library constraints are very easy to use. Each debugging utility is documented fully to help you understand how they work. Here are some simple examples of library use for run-time constraint checking:

        void test_dbg()
        {
            dbg::trace trace(DBG_HERE);

            int  i   = 5;
            int *ptr =

            dbg::assertion(DBG_ASSERTION(i != 6));
            dbg::check_ptr(ptr, DBG_HERE);

            if (i == 5)
            {
                return;
            }

            // Shouldn't get here
            dbg::sentinel(DBG_HERE);
        }

The constraints provided by dbg are:

- dbg::assertion - General purpose assertion (a better `assert`)
- dbg::sentinel - Marker for "shouldn't get here" points
- dbg::unimplemented - Marks unimplemented code
- dbg::check_ptr - Zero pointer check
- dbg::check_bounds - Array bounds checking
- dbg::post_mem_fun - Member function post condition
- dbg::post - General function post condition
- dbg::compile_assertion - Compile time assertion

You can modify constriant behaviour with:

- dbg::set_assertion_behaviour - Set how contraints behave
- dbg::set_assertion_period - Set up trigger periods

See their individual documentation for further details on usage.

You can specify whether constraints merely report a warning, cause an exception to be thrown, or immediately abort the program (see dbg::assertion_behaviour).

For assertions that may fire many times in a tight loop, there is the facility to time-restrict output (see dbg::set_assertion_period)

Using logging

All the constraint checking shown above integrates with the dbg library stream logging mechanisms. These logging facilities are open for your use as well.

Here is a simlpe example of this:

        dbg::attach_ostream(dbg::info, cout);
        // now all 'info' messages go to cout

        dbg::out(dbg::info)    << "This is some info I want to print out\n";

        dbg::out(dbg::tracing) << dbg::indent()
                               << "This is output at 'tracing' level, indented "
                               << "to the same level as the current tracing "
                               << "indent.\n";

When you build without the DBG_ENABLED flag specified, these logging messages will compile out to nothing.

The logging is a very flexible system. You can attach multiple ostreams to any dbg output, so you can easily log to a file and log to the console, for example. The output can be formatted in a number of different ways to suit your needs.

The logging mechanisms provide you with the ability to prepend to all diagnostic output a standard prefix (see dbg::set_prefix), and also to add the diagnostic level and current time to the prefix (see dbg::enable_level_prefix and dbg::enable_time_prefix).

The logging facilities provide by dbg include:

- dbg::enable - Enable/disable activity
- dbg::out - Returns a diagnostic ostream
- dbg::attach_ostream - Attach an ostream to diagnostic output
- dbg::detach_ostream - Detach an ostream to diagnostic output
- dbg::trace - Trace entry/exit points

The output formatting utilities include:

- dbg::set_prefix - Sets the diagnostic output "margin"
- dbg::enable_level_prefix - More information in messages
- dbg::enable_time_prefix - Prints time in messages

Diagnostic sources

The dbg library allows you to differentiate different "sources" of logging.

Each of the debug utilities has a second form in which you can supply a string describing the source of the diagnostic output (see dbg::dbg_source). This source may be a different software component, a separate file - whatever granularity you like!

If you don't specify a dbg::dbg_source then you are working with the ordinary "unnamed" source.

Using these forms you can filter out diagnostics from the different parts of your code. Each source can also be attached to a different set of streams (logging each component to a separate file, for example). The filtering is rich - you can selectively filter each different diagnostic dbg::level for each dbg::dbg_source. For example,

        dbg::enable(dbg::all, "foo-driver", true);
        dbg::enable(dbg::all, "bar-driver", false);

        int i = 5;
        dbg::assertion("foo-driver", DBG_ASSERTION(i != 6));
        dbg::assertion("bar-driver", DBG_ASSERTION(i != 6));

This will trigger an assertion for the "foo-driver" but not the "bar-driver".

There is no requirement to "register" a dbg::dbg_source. The first time you use it in any of the dbg APIs, it will be registered with the dbg library. It comes into an existance as a copy of the "default" debugging sourcei, dbg::default_source.

The default source initially has all debug levels disabled. You can change that with this call. Note that this function only affects sources created after the call is made. Existing sources are unaffected.

If you don't know all of the dbg::dbg_source sources currently available, you can blanket enable/disable them with dbg::enable_all.

It can be tedious to specify the dbg_source in every dbg call in a source file. For this reason, you can specify the DBG_SOURCE compile time macro (wherever you specify DBG_ENABLED). When set, the calls automatically recieve the source name via the DBG_HERE macro (see dbg::source_pos for details). If DBG_SOURCE is supplied but you call a dbg API with a specific named dbg_source, this name will override the underlying DBG_SOURCE name.

Overloads

Each constraint utility has a number of overloaded forms. This is to make using them more convenient. The most rich overload allows you to specify a diagnostic dbg::level and a dbg::dbg_source. There are other versions that omit one of these parameters, assuming a relevant default.

Default states

When your program first starts up the dbg library has all debugging levels switched off. You can enable debugging with dbg::enable. All of the possible dbg::dbg_source enables are also all off for all levels. You can enable these with dbg::enable, or dbg::enable_all.

Initially, the `std::cerr` stream is attached to the dbg::error and dbg::fatal diagnostic levels. You can attach ostreams to the other diagnostic levels with dbg::attach_ostream.

You can modify the "default state" of newly created debug sources. To do this use the special dbg::default_source source name in calls to dbg::enable, dbg::attach_ostream, and and detach_ostream. New sources take the setup from this template source.

All assertion levels are set to dbg::assertions_abort at first, like the standard library's assert macro. You can change this behaviour with dbg::set_assertion_behaviour. There are no timeout periods set - you can change this with dbg::set_assertion_period.

Debugging utilities

Author
  Pete Goodliffe

Version
  1.0

## Typedef Documentation

typedef const char* dbg::dbg_source

typedef for a string that describes the "source" of a diagnostic.

If you are working on a large project with many small code modules you may only want to enable debugging from particular source modules. This typedef facilitiates this.

Depending on the desired granularity of your dbg sources you will use different naming conventions. For example, your dbg_sources might be filenames, that way you can switch off all debugging output from a particular file quite easily. It might be device driver names, component names, library names, or even function names. It's up to you.

If you provide the DBG_SOURCE macro definition at compile time, then the DBG_HERE macro includes this source name, differentiating the sources for you automatically.

See Also
  dbg::enable(level,dbg_source,bool)
  dbg::enable_all

Definition at line 379 of file dbg.h.

typedef std::clock_t dbg::dbgclock_t

The dbgclock_t typedef is an unfortunate workaround for comptability purposes.

One (unnamed) popular compiler platform supplies a <ctime> header file, but this header does NOT place the contents into the std namespace.

This typedef is the most elegant work around for that problem. It is conditionally set to the appropriate clock_t definition.

In an ideal world this would not exist.

This is the version for sane, standards-compliant platforms.

Definition at line 466 of file dbg.h.

typedef const char* dbg::file_name_t

Typedef used in the source_pos data structure.

Describes a filename.

See Also
  dbg::source_pos

Definition at line 411 of file dbg.h.

typedef const char* dbg::func_name_t

Typedef used in the source_pos data structure.

Describes a function name in a source file. (Can be zero to indicate the function name cannot be assertained on this compiler).

See Also
  dbg::source_pos

Definition at line 402 of file dbg.h.

typedef const unsigned int dbg::line_no_t

Typedef used in the source_pos data structure.

Describes a line number in a source file.

See Also
  dbg::source_pos

Definition at line 392 of file dbg.h.

## Enumeration Type Documentation

enum dbg::assertion_behaviour

This enum type describes what happens when a debugging assertion fails.

The behaviour can be:

- assertions_abort - Assertions cause a program abort
- assertions_throw - Assertions cause a dbg_exception to be thrown
- assertions_continue - Assertions cause the standard diagnostic printout to occur (the same as the above behaviours) but execution continues regardless

The dbg library defaults to assertions_abort behaviour, like the standard C `assert`.

See Also
  dbg::set_assertion_behaviour

Definition at line 353 of file dbg.h.

{
assertions_abort,
assertions_throw,
assertions_continue
};

enum dbg::level

The various predefined debugging levels.

The dbg API calls use these levels as parameters, and allow the user to sift the less interesting debugging levels out through dbg::enable.

These levels (and their intended uses) are:

- info - Informational, just for interest
- warning - For warnings, bad things but recoverable
- error - For errors that can't be recovered from
- fatal - Errors at this level will cause the dbg library to abort program execution, no matter what the assertion_behaviour is set to
- tracing - Program execution tracing messages
- debug - Messages about the state of dbg library, you cannot generate messages at this level
- none - For APIs that use 'no level specified'
- all - Used in enable and attach_ostream to specify all levels

Definition at line 325 of file dbg.h.

{
info,
warning,
error,
fatal,
tracing,
debug,
none,
all
};

## Variable Documentation

const int dbg::version = 110

This is the version number of the dbg library.

The value is encoded as version * 100. This means that 100 represents version 1.00, for example.

Definition at line 300 of file dbg.h.