# assert

© 2007 John Abbott
GNU Free Documentation License, Version 1.2

- Examples
- User documentation for files assert.H and assert.C
  - Debugging
- Maintainer documentation for files assert.H and assert.C
- Bugs, Shortcomings, and other ideas

CoCoALib Documentation Index

## Examples

- ex-PolyIterator2.C

## User documentation for files assert.H and assert.C

The only part of `assert.H` which a normal CoCoALib user might find useful is the `CoCoA_ASSERT` macro: it is intended to be a debugging aid.

The `CoCoA_ASSERT` macro does absolutely nothing (not even evaluating its argument) unless the compilation flag `CoCoA_DEBUG` is set. If that flag is set then the macro evaluates its argument to a boolean result which is then tested: if the result is true nothing further happens, if the result is false then the function `CoCoA::AssertionFailed` is called with some arguments indicating which `CoCoA_ASSERT` macro call obtained the false value. The `AssertionFailed` function prints out an informative message on `std::cerr` and then throws a `CoCoA::ERR::AssertFail` exception.

The file `assert.H` contains the following: - definition of the `CoCoA_ASSERT` macro to aid debugging, and the related function `AssertionFailed`

### Debugging

During debugging, a debugger can be used to intercept calls to the function `CoCoA::AssertionFailed` which will stop the program just before throwing the `CoCoA::ERR::AssertFail` exception. This should enable one to find more easily the cause of the problem.

For example, in gdb type

      break CoCoA::AssertionFailed

and then go `up` (perhaps repeatedly) to the offending line.

## Maintainer documentation for files assert.H and assert.C

The macro name `CoCoA_ASSERT` is rather cumbersome, but must contain the prefix `CoCoA_` since macro names cannot be placed in C++ namespaces. The two definitions of the macro (debugging and non-debugging cases) both look rather clumsy, but are done that way so that the macro expands into an expression which is syntactically a simple command. The definition for the non-debugging case I took from `/usr/include/assert.h`; I do not recall where I got the definition for the debugging case, but the definition in `/usr/include/assert.h` looked to be gcc specific.

The purpose of the procedure `AssertionFailed` is explained above in the user documentation (to facilitate interception of failed assertions). The procedure never returns; instead it throws a CoCoALib exception with code `ERR::AssertFail`. Before throwing the exception it prints out a message on `std::cerr` summarising what the assertion was, and where it was. Note the non-standard way of throwing the CoCoA exception: this allows the `ErrorInfo` object to refer to the file and line where `CoCoA_ASSERT` was called (rather then to the line in `assert.C` where `CoCoA_ERROR` is called). The entire printed message is assembled into an `ostringstream` before being printed to ensure exception safety: either the whole message is printed or none of it is, since the printing step is an atomic operation.

## Bugs, Shortcomings, and other ideas

Is the exception safe implementation of `AssertionFailed` excessive?

You have to use explicitly `#ifdef CoCoA_DEBUG` if you want to have a loop or any other non-trivial piece of code executed only when debugging it turned on.

The following (simplified but real) code excerpt is mildly problematic:

      {
        bool OK = ....;
        CoCoA_ASSERT(OK);
      }

When compiled without debugging (i.e. `CoCoA_DEBUG` is zero) the compiler (gcc-3) complains that the variable `OK` is unusued. It does not appear to be possible to make the macro "depend on its argument" in the non-debugging case without incurring the run-time cost of evaluating the argument (if the argument is just a variable the cost is negligible, but if it is a more complex expression then the cost could be considerable). The solution adopted was to modify the calling code like this:

      {
        bool OK;
        OK = ....;
        CoCoA_ASSERT(OK);
      }

Note that the apparently simpler code below will not work if the elided code (i.e. the `....`) has a side effect since the elided code will not be called at all in the non-debugging case:

      {
        CoCoA_ASSERT(....);
      }

POSSIBLE SOLUTION: maybe `CoCoA_ASSERT` could compute `sizeof(...)` in the non-debugging case -- this should avoid evaluation of the argument, and will compile away to nothing.