Various methods and tools for debugging parts of the library or your application. More...
Classes | |
| class | concepts::Assertion |
| Exception class for assertions. More... | |
| class | concepts::Stacktrace |
| Dumps a stack trace using gdb. More... | |
Defines | |
| #define | conceptsThrowSimpleE(msg) |
| Throws a equivalent to conceptsAssert(false, exc) | |
| #define | DEBUGL(doit, msg) |
| Debug Line. | |
Various methods and tools for debugging parts of the library or your application.
This is quite simple: make sure you use the -g flag of the compiler for compiling the library and your application and then use a debugger on the resulting binary. Examples for debuggers are:
I prefer DDD, which should be part of every Linux distribution and is installed on the ETH workstations.
There exists a header file to simplify the creation of debugging output statements: debug.hh. It contains one compiler macros which is important: DEBUGL. This macro is only evaluated if the DEBUG symbol is defined.
In order to have fine grained debugging possibilities, you should use different symbols in a local debugging header file. For instance:
#include "basics/debug.h" #ifndef dgDebug_h #define dgDebug_h #define dgBDiffApplOperator_D 1 #define dgBDiffIntegrateEdge_D 0 #endif
In our example, all statements with dgBDiffApplOperator_D are executed. Such a statement could look like this:
DEBUGL(dgBDiffApplOperator_D, "elmX: " << quadX.key() << ", elmY:", quadY.key());
The output of the statment above looks like
[../dg/dgBForm.cc, line 36] dg_BDiffusion::operator() -- elmX: 1, elmY: 0
If you have more complex statements which you would like to hide for production use, you can do something like the following
#if dgBDiffApplOperator_D cout << "[" << __FILE__ << ", line " << __LINE__ << "] dg_BDiffusion::operator() --" << endl; cout << "blah blub" << endl; #endif
Like before, these statements are only executed (and even only compiled) if DEBUG is defined and dgBDiffApplOperator_D is true (ie. non-zero).
The class concepts::Assertion can be used to assert certain conditions.
#include "basics/exceptions.hh" // ... const int* m = dynamic_cast<const int*>(n); conceptsAssert(m != 0, Assertion()); cout << *m << endl; // ... conceptsAssert3(a == b, Assertion(), "a = " << a << ", b = " << b);
If the assertion fails, an exception of type concepts::Assertion is thrown. If the macro conceptsAssert3 is used instead of conceptsAssert, the additional information given as the third argument is printed in case of an error. It can be caught by
try { // here, an assertion might fail } catch (Assertion& e) { std::cout << e << std::endl; }
Instead of catching Assertion it is also possible to catch ExceptionBase (the base class of all exceptions in the library).
In case an assertion fails, a stacktrace is printed by calling gdb in concepts::Stacktrace::print. This can be controlled by concepts::Stacktrace::doit:
concepts::Stacktrace::doit() = false;
inhibits printing stack traces.
| #define conceptsThrowSimpleE | ( | msg | ) |
{ \
std::stringstream errorMsg; \
errorMsg << msg; \
exception_throw_assert(std::string(__FILE__), __LINE__, \
std::string(__PRETTY_FUNCTION__), \
std::string("SimpleException"), errorMsg.str(), concepts::Assertion()); \
}
Throws a equivalent to conceptsAssert(false, exc)
Definition at line 366 of file exceptions.hh.
| #define DEBUGL | ( | doit, | |
| msg | |||
| ) |
DPL(doit, "[34m[" << concepts::shorten(__FILE__) << ':' << std::setw(4) \ << __LINE__ << "][m " << DEBUG_FUNCTION << " --", msg)
Debug Line.
Prints a debugging message with information about file, line and function where it is located. At the end, the line is wrapped. The message looks like
[file.cc, line 62] void function(double) -- this is the message
| doit | The line is only printed if true |
| msg | Text in a stream (can include variables etc.) to be printed |