3 Nobug is a simple debugging library (only a single nobug.h header) similar to
4 gnu-nana and Design-by-Contract ideas.
8 Nobug provides you with:
10 * Three different levels for checks (in depth to final no-overhead)
11 * Scope tags (tell whenever a function or loop is considered to be bug free)
12 * Pre-, Postcondition and Invariant checks, generic Assertions
13 * Debugger support (actions are only executed while running under a
14 debugger), currently only valgrind
15 * Dumping of your datastructures
16 * Logging your application's activities
17 * Runtime customizable logging via an enviromnet variable
18 * Different logging targets (stderr, syslog, debugger...)
19 * Annotation of your sourcecode about known bugs, things to do and planned
26 Nobug uses different levels of checks:
29 + for expensive testing and logging while developing the software
31 + for testers and users who want to try the software
33 + finished version for end users
35 Release builds remove all assertions (but some logging is kept) we make the
36 assumption that bugs which where not covered in alpha and beta builds won't be
37 easily show up in releases because the assertions there where not sufficent.
38 Further end users are not test bunnies and wont provide good bug reports
39 anyways. If there is a problem in a release build, then try to investigate the
40 cause with a beta build from the same source.
42 To define a debug level for compilation just use '-DEBUG_ALPHA', '-DEBUG_BETA'
43 for Debug Builds or the standard '-DNDEBUG' for a release build. Nobug will
44 complain if none of this is defined.
48 The programmer can tag any Scope as UNCHECKED or CHECKED. In ALPHA and BETA
49 builds a global UNCHECKED is implied, while in RELEASE builds a global CHECKED
50 is used and UNCHECKED Scopes are not allowed.
54 Here is a table which basic assertions gets checked on each level/scope
58 UNCHECKED Preconditions, Postconditions, Preconditions, compiling will
59 Invariants Postconditions abort
60 CHECKED Preconditions, Postconditions Preconditions
64 Nobug is almost completely implemented in preprocessor macros, this is needed
65 because it uses the __FILE__ and __LINE__ macros for logging. All its flat
66 namespace uppercase identifiers make it good recognizeable in a source too.
68 All macros are unconditionally available with NOBUG_ prefixed, for convinience
69 there are also macros without this prefix unless such a macro was already
70 defined. For each Assertion and Logging macro there is a form with _DBG as
71 suffix which will be only active under a debugger. The _DBG versions are only
72 enabled in alpha builds.
74 There are also assertions with a _IF suffix taking a 'when' parameter as first
77 * REQUIRE_IF(foo!=NULL, foo->something == constrained)
79 they only perform the assertion when when is true. The debugger versions are
80 available as _IF_DBG prefixed macros.
84 when assertion is only performed if expression 'when' is true at runtime
85 expr test without side effects
86 fmt printf like formatstring
87 ... if not preceeded by 'fmt' then printf like formatstring else only its
89 what reason for a failure as string literal
90 flag flag for enabling custom logging groups
91 type type of the to be checked data as single identifier name
92 pointer pointer to type
94 depth depth for invariants and dumps
99 + Precondition (input) check
101 + Postcondition (progress/output) check
102 ASSERT(expr, what, ...)
104 INVARIANT(type, pointer, depth)
105 + Checking invariants
109 Logging is controlled by user defined flags and a log limit.
113 Each Log macro has a explicit or implicit Log-Level which correspondends to
114 syslog levels. Logging is only emitted when the current NOBUG_LOG_LIMIT is more
115 servere than the one of the Log message.
117 * In ALPHA builds, NOBUG_LOG_LIMIT_ALPHA is used which defaults to LOG_INFO
118 * In BETA builds, NOBUG_LOG_LIMIT_BETA is used and defaults to LOG_WARNING
119 * In RELEASE builds, NOBUG_LOG_LIMIT_RELEASE is used and defaults to LOG_CRIT
121 You can override all of those three with your own preference. Alternatively
122 NOBUG_LOG_LIMIT can be defined by the user to override all defaults.
124 Further the NOBUG_LOG_LIMIT can be initialized in ALPHA and BETA builds by the
125 NOBUG_LIMIT enviroment variable. The NOBUG_INIT_FLAG below takes care of this.
129 Flag is just a C identifier and should be declared with
131 * NOBUG_DECLARE_FLAG(flagname)
133 preferably in one of your headers
135 Further it must be defined with
137 * NOBUG_DEFINE_FLAG(flagname)
141 * NOBUG_DEFINE_FLAG_LIMIT(flagname, level)
143 in one of your source files
147 * NOBUG_INIT_FLAG(flagname)
149 once at the start of your program for every flag defined with NOBUG_DEFINE_FLAG
151 Flags are initially set to -1 (nothing gets logged), NOBUG_INIT_FLAG(flagname)
152 checks if flagname is present in the environment variable 'NOBUG_LOG' and then
153 sets the flag to the current limit. You can query the flag state with
154 NOBUG_FLAG(flagname).
156 There is a predefined flag NOBUG_ON which is always enabled.
161 2 NOBUG_DEFINE_FLAG (test);
164 5 NOBUG_INIT_FLAG (test);
166 7 INFO (test, "Logging enabled");
167 8 INFO (NOBUG_ON, "Always on");
172 $ tcc -DEBUG_ALPHA -run example.c
173 DEBUG: main : Always on
174 $ NOBUG_LOG=test tcc -DEBUG_ALPHA -run example.c
175 DEBUG: main : Logging enabled
176 DEBUG: main : Always on
177 $ NOBUG_LIMIT=CRIT NOBUG_LOG=test tcc -DEBUG_ALPHA -run example.c
178 DEBUG: main : Always on
182 These macros log with implicit Log Level, note that there are no more servere
183 levels than LOG_ERROR since these should be handled by Assertions in a
186 * ERROR(flag, fmt, ...)
187 ERROR_IF(expr, rflag, fmt, ...)
188 + Application takes a error handling brach
191 WARN_IF(expr, flag, fmt, ...)
192 + Rare, handled but unexpected branch
195 INFO_IF(expr, flag, fmt, ...)
196 + Message about program progress
198 NOTICE(flag, fmt, ...)
199 NOTICE_IF(expr, flag, fmt, ...)
202 TRACE(flag, fmt, ...)
203 TRACE_IF(expr, flag, fmt, ...)
204 + Very fine grained messages
206 Note that TRACE correspondends to LOG_DEBUG, using 'DEBUG' could be ambiguous.
208 There is one generic LOG macro which takes the level explicitly:
210 * LOG(flag, lvl, fmt, ...)
211 LOG_IF(expr, flag, lvl, fmt, ...)
213 Dumping Datastructures
215 * DUMP(type, pointer, depth)
216 + Dump a datastructure
217 DUMP_IF(expr, type, pointer, depth)
218 + Dump datastructure if expr is true
220 How to write DUMP handlers
226 3 int INTEGER_MEMBER;
227 4 char * STRING_MEMBER;
228 5 struct STRUCTNAME* next;
231 then you define a function like:
234 2 nobug_STRUCTNAME_dump (const struct STRUCTNAME* self,
239 7 // check for self != NULL and that the depth
240 8 // limit did not exceed in recursive datastructures
243 11 // use DUMP_LOG not LOG to print the data
244 12 DUMP_LOG("STRUCTNAME %p: int is %d, string is %s", self,
245 13 self->INTEGER_MEMBER,
246 14 self->STRING_MEMBER);
247 15 // now recurse with decremented depth
248 16 nobug_STRUCTNAME_dump (self->next, depth-1, file, line);
252 now you can use the DUMP() macros within the code
256 3 struct STRUCTNAME foo;
258 5 DUMP (STRUCTNAME, &foo, 2);
263 One can tagging features as:
266 + important, not yet finished feature
268 + planned for future feature
270 + known bug to be fixed later
272 + enhancement to be done soon
274 + used to tag code-path which shall be never executed (defaults in switch
275 statements, else NOTREACHED after series of if's)
277 The advantage of this tagging over plain source comments is that we can take
278 some actions if we run in such a tag at compile or runtime:
280 the action to be taken when such a macro is hit depends on the build level:
283 UNIMPLEMENTED abort abort wont compile
284 BUG log abort wont compile
285 TODO log log wont compile
286 PLANNED log nothing nothing
287 NOTREACHED abort abort removed
291 * abort means first log and then abort
292 * log will only log once for each sourceline (not on each hit)
293 * wont compile will abort compilation with a error message
294 * nothing optimized out, sane way
295 * removed optimized out for performance reasons
302 This Documentation is maintained at:
304 * http://www.pipapo.org/pipawiki/NoBug/Documentation
306 NoBug/Documentation (last edited 2007-01-25 18:23:45 by ct)