Logo Search packages:      
Sourcecode: libdbg version File versions  Download package

dbg Namespace Reference


Detailed Description

Debugging utilities.

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:

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:

You can modify constriant behaviour with: 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:

The output formatting utilities include: 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.

Author:
Pete Goodliffe
Version:
1.0


Classes

struct  assertion_exception
struct  check_ptr_exception
class  compile_assertion
struct  dbg_exception
struct  indent
class  null_stream
class  post
class  post_mem_fun
struct  prefix
struct  sentinel_exception
struct  source_pos
class  trace
struct  unimplemented_exception

Typedefs

typedef const char * dbg_source
typedef std::clock_t dbgclock_t
typedef const char * file_name_t
typedef const char * func_name_t
typedef const unsigned int line_no_t

Enumerations

enum  assertion_behaviour { assertions_abort, assertions_throw, assertions_continue }
enum  level {
  info, warning, error, fatal,
  tracing, debug, none, all
}

Functions

void assertion (void *)
void assertion (dbg_source, void *)
void assertion (level, void *)
void assertion (level, dbg_source, void *)
void assertion (dbg::level lvl, dbg::dbg_source src, const assert_info &info)
void attach_ostream (dbg::level lvl, dbg::dbg_source src, std::ostream &o)
void attach_ostream (dbg::level lvl, std::ostream &o)
void check_bounds (int, void *, void *)
void check_bounds (void *, int, void *, void *)
void check_bounds (level, int, void *, void *)
void check_bounds (level, dbg_source, int, int, void *, void *)
void check_bounds (level, dbg_source, int, void *, void *)
void check_bounds (level, void *, int, int, void *)
void check_bounds (dbg::level lvl, dbg::dbg_source src, int index, int bound, const source_pos &here)
void check_ptr (const void *, void *)
void check_ptr (dbg_source, const void *, void *)
void check_ptr (level, const void *, void *)
void check_ptr (level, dbg_source, const void *, void *)
void check_ptr (dbg::level lvl, dbg::dbg_source src, const void *p, const source_pos &here)
void detach_all_ostreams (dbg::level lvl, dbg::dbg_source src)
void detach_all_ostreams (dbg::level lvl)
void detach_ostream (dbg::level lvl, dbg::dbg_source src, std::ostream &o)
void detach_ostream (dbg::level lvl, std::ostream &o)
void enable (dbg::level lvl, dbg::dbg_source src, bool enabled)
void enable (dbg::level lvl, bool enabled)
void enable_all (dbg::level lvl, bool enabled)
void enable_level_prefix (bool enabled)
void enable_time_prefix (bool enabled)
null_stream error_out ()
null_stream fatal_out ()
null_stream info_out ()
std::ostream & operator<< (std::ostream &s, const source_pos &pos)
std::ostream & operator<< (std::ostream &s, const indent &i)
std::ostream & operator<< (std::ostream &s, const prefix &p)
null_stream out (level)
std::ostream & out (dbg::level lvl, dbg::dbg_source src)
void sentinel (void *)
void sentinel (dbg_source, void *)
void sentinel (level, void *)
void sentinel (level, dbg_source, void *)
void sentinel (dbg::level lvl, dbg::dbg_source src, const source_pos &here)
void set_assertion_behaviour (level lvl, dbg::assertion_behaviour b)
void set_assertion_period (dbgclock_t p)
void set_prefix (const char *pfx)
null_stream trace_out ()
void unimplemented (void *)
void unimplemented (dbg_source, void *)
void unimplemented (level, void *)
void unimplemented (level, dbg_source, void *)
void unimplemented (dbg::level lvl, dbg::dbg_source src, const source_pos &here)
null_stream warning_out ()

Variables

const dbg_source default_source = 0
const int version = 110


Generated by  Doxygen 1.6.0   Back to index