3 * "Everyone makes errors, but with NoBug you won't make them twice!"
5 Nobug is a simple debugging library for instrumenting C and C++ programs
6 inspired from Design-by-Contract ideas.
10 Nobug provides you with the following:
12 * Three different levels for checks - in depth to final no-overhead
13 * Scope tags - tell whenever a function or loop is considered to be bug free
14 * Preconditional, Postcondition and Invariant checks, generic Assertions
15 * Debugger support (actions are only executed while running under a
16 debugger), currently only valgrind
17 * Dumping of your datastructures
18 * Logging your application's activities
19 * Runtime customizable logging via an enviromnet variable
20 * Different logging targets (stderr, syslog, debugger...)
21 * Annotation of your sourcecode about known bugs, things to do, etc.
22 * Tracking Resources (Files, Locks, etc.) used by your programm; help in
25 Building and Installing
29 Release tarballs are attached to this wiki at:
31 * http://pipawiki/NoBug?action=AttachFile
33 I am using gpg signed tarballs for distribution. As first step one has to check
36 $ gpg nobug-X.Y.tar.gz.gpg
38 This will produce a nobug-X.Y.tar.gz and report if the signature could be
41 Since they are built with gnu autotools, the usual build and install procedure
44 $ tar xzvf nobug-X.Y.tar.gz
50 Development Version via git
52 The devlopment version is available via git from 'git://git.pipapo.org/nobug'
53 or mirrored at repo.or.cz 'git://repo.or.cz/nobug.git'.
55 After you cloned the repository you need to bootstap the autotools first
59 Then the usual ./configure && make && make install will work.
61 There is a special makefile target make meta to bring serveral files (README,
62 AUTHORS, NEWS) in sync with the NoBug Documentation wiki and update the
67 Currently, NoBug installs the following:
69 * A single nobug.h headerfile which your code will use
70 * Two libs for static linking:
71 + 'libnobug.a' for singlethreaded programs
72 + 'libnobugmt.a' for multithreaded programs.
76 You can make Nobug features available either by installing it as described
77 above or by shipping the nobug sources along with your project.
79 To use NoBug, some controling preprocessor macros have to be defined. The
80 nobug.h header should then be included.
82 A project using NoBug should use autoconf to check for execinfo.h and valgrind/
85 AC_CHECK_HEADERS([execinfo.h valgrind/valgrind.h])
87 For Multithreaded programs, you should also check for pthread.h.
89 When the resulting HAVE_PTHREAD_H, HAVE_EXECINFO_H and HAVE_VALGRIND_VALGRIND_H
90 are defined by the configure script, the corresponding features become
93 NoBug then defines 'NOBUG_USE_PTHREAD', 'NOBUG_USE_VALGRIND' and
94 'NOBUG_USE_EXECINFO' to 1. If you do not want to use any of these features in
95 NoBug, you can define these macros to 0 before including nobug.h.
97 If NVALGRIND is defined, valgrind support will not be used.
99 There are many other macros which can be set and overridden by the user to
100 control the behavior. Please edit the Documentation wiki when you find them
103 A program using NoBug should be linked against 'libnobug.a' if it is
104 singlethreaded or against 'libnobugmt.a' if it is multithreaded. The Library
105 must be initialized with NOBUG_INIT before using any other features or creating
106 threads. This is discussed in more detail at NoBug/Documentation/Macros/
113 Nobug uses the following different levels of checks:
116 + for expensive testing and logging while developing the software
118 + for testers and users who want to try the software
120 + finished version for end users
122 Release builds remove all assertions, but some logging is kept. We make the
123 assumption that bugs which where not covered in alpha and beta builds will not
124 easily show up in releases because the assertions there where not sufficent.
125 Further, end users are not test bunnies and will not provide good bug reports
126 anyway. If there is a problem in a release build, try to investigate the cause
127 with a beta build from the same source.
129 To define a debug level for compilation, just use '-DEBUG_ALPHA' or
130 '-DEBUG_BETA' for bebug builds and use the standard '-DNDEBUG' for a release
131 build. Nobug will complain if the debug level has not been defined.
135 The programmer can tag any Scope as UNCHECKED or CHECKED. In ALPHA and BETA
136 builds, a global UNCHECKED is implied. In RELEASE builds, UNCHECKED Scopes are
141 Here is a table of which basic assertions gets checked on each level/scope
145 UNCHECKED Preconditions, Postconditions, Preconditions, compiling will
146 Invariants Postconditions abort
147 CHECKED Preconditions, Postconditions Preconditions
151 The NoBug interface is almost completely implemented in preprocessor macros.
152 This is needed because it uses the __FILE__ and __LINE__ macros for logging.
153 All of the flat namespace uppercase identifiers make it easily recognizeable
154 within source code too.
156 All macros are unconditionally available with NOBUG_ prefixed. For convenience,
157 there are also macros without this prefix as long as such a macro was not
158 already defined. For each Assertion and Logging macro, there is a form with the
159 suffix _DBG which will be only active under a debugger. The _DBG versions are
160 only enabled in alpha builds.
162 When NOBUG_DISABLE_SHORTNAMES is defined by the user, then only the NOBUG_
163 prefixed macros are available and the short ones will never be defined.
165 There are also assertions with an _IF suffix taking a 'when' parameter as first
166 argument. The following is an example:
168 * REQUIRE_IF(foo!=NULL, foo->something == constrained)
170 The assertion will only be performed when when is true. The debugger versions
171 are available as _IF_DBG prefixed macros.
175 when Assertion is only performed if expression 'when' is true at runtime
176 expr Test without side effects
177 fmt printf like formatstring
178 ... If not preceeded by 'fmt', then printf like formatstring. Otherwise,
180 flag Flag for enabling custom logging groups
181 type Type of the data to be checked as a single identifier name
182 pointer Pointer to type
184 depth Depth for invariants and dumps
194 before using any other NoBug feature. Probably in main or any other library
195 initialization routine. Calling NOBUG_INIT more than once is supported and each
196 subsequent call will be a no-op, thus initialization in main and in libraries
201 If you want to use environment variable controlled debuging, then you have to
202 initialize each flag with
204 * NOBUG_INIT_FLAG(flagname)
208 * NOBUG_INIT_FLAG_LIMIT(flagname, default)
210 This is documented later in NoBug/Documentation/Macros/LoggingConfiguration.
212 * <!> These two macros call NOBUG_INIT for backward compatibility.
216 In Multithreaded programs you should assign an identifier to each thread after
219 * NOBUG_THREAD_ID_SET(name)
221 If you don't call it, then NoBug will assign a automatic identifier. This is
222 documented in NoBug/Documentation/Macros/MultiThreading.
227 + Precondition (input) check. Use these macros to validate input a
228 function recieves. The checks are enabled in ALPHA and BETA builds and
229 optimized out in RELEASE builds.
232 + Postcondition (progress/output) check. Use these macros to validate the
233 data a function produces (example: return value). The checks enabled
234 unconditionally in ALPHA builds and optimized out in BETA builds for
235 scopes which are tagged as CHECKED. In RELEASE builds this checks are
236 always optimized out, but scopes tagged as UNCHECKED are not permitted.
239 + Generic check. Use these macros when you want to validate something
240 which doesn't fall into one of the above categories. A example is when
241 a library function can return a unexpected result (scanf with syntax
242 error in the formatstring, when a constant/literal formatstring is
243 expected). The checks are enabled in ALPHA and BETA builds and
244 optimized out in RELEASE builds.
247 + Nobug overrides the standard assert macro in ALPHA and BETA builds.
248 This is just a compatibility feature, its use is not suggested.
250 INVARIANT(type, pointer, depth)
251 + Checking invariants. You can provide more complex checking functions
252 which test the validity of datastructures. Invariants are only enabled
253 in ALPHA builds for scopes which are not tagged as CHECKED and
254 otherwise optimized out. (TODO: document how to write invariants)
258 Nearly all NoBug Macros emit some log message. NoBug gives the user fine
259 grained control over these log messages to display only interesting information
260 without loosing details.
262 Log messages are routed to different destinations which are:
265 + The underlying storage backend. Messages are appended to the end of the
266 buffer, overwriting older messages at the front of the buffer. NoBug
267 comes with a highly efficent ringbuffer implementation.
269 + This is either just stderr or if running under valgrind then valgrind
270 facilities to include messages into its log will be used.
272 + The user can open Files for log messages.
274 + Messages are send to the standard system logging daemon.
276 + There is a interface which allows the programmer to catch logmessages
277 and display them in a application defined way.
279 Each logmessage has a priority descibing its severity in the same way as syslog
282 All non-fatal messages are associated with a programmer defined flag describing
283 the source of the message (subsystem, module, ...).
285 Putting it all together: A user can define which source/flag shall be logged at
286 what priority level and to which destination. To make this all easier NoBug
287 tries to give reasonable defaults.
293 Each Log macro has a explicit or implicit Log-Level which correspondends to
294 syslog levels. Logging is only emitted when the messages is more servere than a
297 The defaults look like:
300 ringbuffer TRACE INFO NOTICE ringbuffer must always be most verbose
301 console INFO NOTICE -1 no log to console in release
302 file TRACE NOTICE WARNING
303 syslog -1 NOTICE WARNING no syslog for test runs
304 application INFO WARNING ERROR
306 Depending on the build level there is a default logging target and a default
307 limit which is choosen when the user doesn't specify one.
309 The default limits are:
311 * In ALPHA builds, NOBUG_LOG_LIMIT_ALPHA is used which defaults to LOG_INFO
312 * In BETA builds, NOBUG_LOG_LIMIT_BETA is used and defaults to LOG_WARNING
313 * In RELEASE builds, NOBUG_LOG_LIMIT_RELEASE is used and defaults to LOG_CRIT
315 The default targets are:
317 * In ALPHA builds, NOBUG_LOG_TARGET_ALPHA is used which defaults to
319 * In BETA builds, NOBUG_LOG_TARGET_BETA is used and defaults to
321 * In RELEASE builds, NOBUG_LOG_TARGET_RELEASE is used and defaults to
324 You can override all of those values with your own preference. Alternatively
325 NOBUG_LOG_LIMIT and NOBUG_LOG_TARGET can be defined by the user to override all
330 Flags are used to tell NoBug about subsystems/modules or even finer grained
333 A Flag should be declared with
335 * NOBUG_DECLARE_FLAG(flagname)
337 preferably in one of your headers
339 Further it must be defined with
341 * NOBUG_DEFINE_FLAG(flagname)
345 * NOBUG_DEFINE_FLAG_LIMIT(flagname, limit)
347 in one of your source files
351 * NOBUG_INIT_FLAG(flagname)
355 * NOBUG_INIT_FLAG_LIMIT(flagname, default)
357 once at the start of your program for every flag.
359 For flags defined with NOBUG_DEFINE_FLAG(flagname) the defaults are initialized
360 as in the table above, while NOBUG_DEFINE_FLAG_LIMIT(flagname, level) is used
361 to initialize the default target (depending on build level) to limit. Calling
362 NOBUG_INIT_FLAG(flagname) is optional for limit initialized flags.
364 NOBUG_INIT_FLAG(flagname) parses the environment variable '$NOBUG_LOG' for
365 flagname, the syntax is as following:
367 logdecl_list --> logdecl, any( ',' logdecl_list).
369 logdecl --> flag, opt(limitdecl, any(targetdecl))
371 flag --> "identifier of a flag"
373 limitdecl --> ':', "LIMITNAME"
375 targetdecl --> '@', "targetname", opt(targetopts)
377 targetopts --> '(', "options for target", ')', opt(targetopts)
379 Roughly speaking, NOBUG_LOG contains a comma separated list of declarations for
380 flags which are the name of the flag followed by a limit which is written in
381 all uppercase letters and preceeded by a colon, followed by target declarations
382 which are names of the targets, introduced by a at sign. Target declarations
383 can have options in future which is not yet implemented. Limit and target
384 declarations are optional and then choosen from the defaults table above. These
385 defaults are currently just an guess what should be useable and might be
388 <!> NOTE: '(options)' on targets are not yet implemented!
392 NOBUG_LOG='flag,other' # set the limit of the default target a default limit (see table above)
393 NOBUG_LOG='flag:DEBUG' # set the limit of the default target to DEBUG
394 NOBUG_LOG='flag:DEBUG@console@syslog' # set console and syslog limits for flag to DEBUG
395 NOBUG_LOG='flag:DEBUG,other:TRACE@ringbuffer'
397 There is a predefined flag NOBUG_ON which is always enabled.
402 2 NOBUG_DEFINE_FLAG (test);
407 7 NOBUG_INIT_FLAG (test);
409 9 INFO (test, "Logging enabled");
410 10 INFO (NOBUG_ON, "Always on");
415 $ tcc -DEBUG_ALPHA -run example.c
416 example.c:10: debug: INFO: main: Always on
418 $ NOBUG_LOG=test tcc -DEBUG_ALPHA -run example.c
419 example.c:9: debug: INFO: main: Logging enabled
420 example.c:10: debug: INFO: main: Always on
424 These macros log with implicit Log Level, note that there are no more servere
425 levels than LOG_ERROR since these should be handled by Assertions in a
428 * ERROR(flag, fmt, ...)
429 ERROR_IF(expr, rflag, fmt, ...)
430 + Application takes a error handling brach
433 WARN_IF(expr, flag, fmt, ...)
434 + Rare, handled but unexpected branch
437 INFO_IF(expr, flag, fmt, ...)
438 + Message about program progress
440 NOTICE(flag, fmt, ...)
441 NOTICE_IF(expr, flag, fmt, ...)
444 TRACE(flag, fmt, ...)
445 TRACE_IF(expr, flag, fmt, ...)
446 + Very fine grained messages
448 Note that TRACE correspondends to LOG_DEBUG, using 'DEBUG' could be ambiguous.
450 There is one generic LOG macro which takes the level explicitly:
452 * LOG(flag, lvl, fmt, ...)
453 LOG_IF(expr, flag, lvl, fmt, ...)
455 Dumping Datastructures
457 * DUMP(flag, type, pointer, depth)
458 + Dump a datastructure
459 DUMP_IF(expr, flag, type, pointer, depth)
460 + Dump datastructure if expr is true
462 How to write DUMP handlers
468 3 int INTEGER_MEMBER;
469 4 char * STRING_MEMBER;
470 5 struct STRUCTNAME* next;
473 then you define a function like:
476 2 nobug_STRUCTNAME_dump (const struct STRUCTNAME* self,
482 8 // check for self != NULL and that the depth
483 9 // limit did not exceed in recursive datastructures
484 10 if (self && depth)
486 12 // use DUMP_LOG not LOG to print the data
487 13 DUMP_LOG("STRUCTNAME %p: int is %d, string is %s", self,
488 14 self->INTEGER_MEMBER,
489 15 self->STRING_MEMBER);
490 16 // now recurse with decremented depth
491 17 nobug_STRUCTNAME_dump (self->next, depth-1, file, line, func);
495 now you can use the DUMP() macros within the code
499 3 struct STRUCTNAME foo;
501 5 DUMP (my_flag, STRUCTNAME, &foo, 2);
504 Dumping is by default done on level LOG_DEBUG, this can be overridden by
505 defining NOBUG_DUMP_LEVEL to some other level, further DUMP_IF is the only
506 enabled dumping macro for the RELEASE build level.
510 One can tagging features as:
513 + Something which shouldn't be used in future.
515 + important, not yet finished feature
517 + planned for future feature
519 + known bug to be fixed later
521 + enhancement to be done soon
523 + used to tag code-path which shall be never executed (defaults in switch
524 statements, else NOTREACHED after series of if's)
526 The advantage of this tagging over plain source comments is that we can take
527 some actions if we run in such a tag at compile or runtime:
529 the action to be taken when such a macro is hit depends on the build level:
532 DEPRECATED log nothing wont compile
533 UNIMPLEMENTED abort abort wont compile
534 FIXME log wont compile wont compile
535 TODO log log wont compile
536 PLANNED log nothing nothing
537 NOTREACHED abort abort removed
541 * abort means first log and then abort
542 * log will only log once for each sourceline (not on each hit)
543 * wont compile will abort compilation with a error message
544 * nothing optimized out, sane way
545 * removed optimized out for performance reasons
549 <!> This part is work in progress, interfaces may change
551 With little effort, NoBug can watch all kinds of resources a program uses. This
552 becomes useful for resources which are distributed over a potentially
553 multithreaded program. Resource tracking is only active in ALPHA builds and
554 optimized out in BETA and RELEASE builds.
558 Resources are abstracted, NoBug doesn't know anything about the Semantics of a
559 resource, it only keeps records of resources and the code using it and ensures
560 basic constraints. Detailed use checks of resource have to be done with other
563 Resources are identified by c-strings, there are some optimizations to make
564 this very efficent. They can be announced by a 'type' and 'name' pair from
565 which NoBug creates (copies) a 'type:name' identifier or by supplying a string
566 which must be available through the entire lifetime of the resource, NoBug will
567 then only reference this string.
569 Code which wants to use a resource calls a enter macro with its own identifier
570 and a leave macro when finished with it.
574 Certain operations could use a 'handle' which will improve performance
575 considerably. These handles are defined with
577 * RESOURCE_HANDLE(name)
579 This macro takes care that the declaration is optimized out in the same manner
580 the rest of the resource tracker would be disabled. You can still instantiate
581 handles as struct nobug_resource_record* in structures which must have a
582 constant size unconditional of the build level. It is important to note that
583 macros which take the handle as last optional parameter must be given as
584 pointer to pointer with &handle, while when using it as target for a macro as
585 first parameter its used just normally as pointer.
587 Resources are published by
589 * RESOURCE_ANNOUNCE(type, name[, &handle])
593 * RESOURCE_ANNOUNCE_LITERAL(identifier[, &handle])
595 Resources must be unique, it is a fatal error when a resource it tried to be
596 announced more than one time.
598 * 'type' is a cstring which should denote the domain of the resource, the
599 type "nobug" is reserved for internal use. Other strings are freely
600 chooseable, examples are "file" "mutex" "lock" "database" and so on.
601 * 'name' is the actual name of a named resource this is a cstring which
602 together with type forms a unique identifier of the resource. 'type' and
603 'name' are assembled to a new string seperated by a colon and thus can be
604 volatile strings. Example 'type' = "file" and 'name' = "/etc/passwd" will
605 create a identifier "file:/etc/passwd" for this resource.
606 * 'identifier' must be a static string which is available throughout the
607 lifetime of the resource, it will only be referenced, the implementation is
608 little more efficent this way, but you are more constrained about the name.
609 * 'handle' is a pointer to a nobug_resource_record* which will be initialized
610 to point to the newly created resource. If it is feasible to store this
611 pointer somewhere, where clients can access it then the enter/leave below
612 can be done more efficent because the resource record doesnt need to be
615 When a resource becomes unavailable it is removed from the registry by
617 * RESOURCE_FORGET(type, name[, &handle])
621 * RESOURCE_FORGET_LITERAL(identifier[, &handle])
623 The resource must still exist and no users must be attacched to it, else a
624 fatal error is raised. The parameters are the same here as for
625 RESOURCE_ANNOUNCE above. 'handle' will be set to NULL and should be provided
626 here when used while announcing because the nulling has to be done in a lock
627 when using multithreading.
629 Code which wants to use a resource attaches to it by
631 * RESOURCE_ENTER(type, name, client[, handle])
635 * RESOURCE_ENTER_LITERAL(identifier, clientid[, handle])
639 * RESOURCE_ENTER_HANDLE(handle, user[, handle])
641 When finished with using the resource you dissconnect from it with
643 * RESOURCE_LEAVE(type, name, user[, handle])
647 * RESOURCE_LEAVE_LITERAL(name, user[, handle])
651 * RESOURCE_LEAVE_HANDLE(handle, user[, handle])
653 There is special support for resources which might block during acquisition
654 (blocking IO, locks, ...). Such resources are entered just before you actually
655 do the call to the resource and after you aquired it you call
657 * RESOURCE_ACQUIRED_HANDLE(handle)
659 This just attaches the string "acquired" to the resource record which will be
662 Just a simple example:
666 3 // define a mutex and announce it
667 4 pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
668 5 RESOURCE_ANNOUNCE_NAME("mutex", "my_mutex");
670 7 // the following would be actually done in a different thread in a real program
671 8 RESOURCE_HANDLE(e); // define a handle
672 9 RESOURCE_ENTER_NAME("mutex", "my_mutex", "example", &e); // announce that we want to use the resource
673 10 pthread_mutex_lock (&my_mutex); // this might block
674 11 RESOURCE_ACQUIRED_HANDLE(e1); // we got it, now announce that
676 13 // program does something useful here
678 15 RESOURCE_LEAVE_NAME("mutex", "my_mutex", "example"); // announce that we dont need it anymore
679 16 pthread_mutex_lock (&my_mutex); // and instantly unlock
682 19 // back in the main thread
683 20 RESOURCE_FORGET_NAME("mutex", "my_mutex"); // remove the resource from the public registry
688 The Resource Tracker is neither bullet-proof nor exact in the current state.
689 There are small race conditions in the time we announce/forget/enter/remove
690 resources and doing the actual call to a resource. These race conditions affect
691 the reporting exactness in certain corner cases and are a design decision, for
692 practical use they should be no danger. More important is that the Resource
693 Tracker relies on that announce/forget and enter/leave are properly paired. The
694 programmer should ensure that this is done right, else it will become
695 unuseable. This will be fixed in future NoBug versions.
697 The underlying resource-tracking library may report errors, all these errors
698 are fatal for NoBug and trigger an abort(). When such an error occurs the
699 Resource Tracker is left in a locked state, which is harmless for generating
700 reports prior the abort.
704 It is important that NoBug protects certain operations with locks in
705 multithreaded programs. You have to ensure that 'HAVE_PTHREAD_H' is defined by
706 the configuration system and use the 'libnobugmt.a' library for linking. It is
707 particular important that libraries using NoBug are compiled with
708 'HAVE_PTHREAD_H' enabled when they are intended to be used in multithreaded
711 When Multithreading is used, log messages contain a identifier of the
712 orginating thread. This identifier should be set by
714 * NOBUG_THREAD_ID_SET(name)
716 right after thread creation. name is a string describing the purpose of the
717 thread. Nobug will assemble a unique identifier by appending a underscore and a
718 number to name, for example NOBUG_THREAD_ID_SET("gui") will result in a
719 identifier like "gui_5". When you don't set a thread identifier, then NoBug
720 assigns one automatically with the name 'thread' preprended if needed. Thread
721 identifiers are immutable once set.
723 For querying the thread identifier you use
725 * NOBUG_THREAD_ID_GET
727 which will return a const char* to the thread id in multithreaded programms and
728 a pointer to a literal "" in singlethreaded programs.
739 <!> this section is very work in progress
744 + Write a testsuite, build your program with -O0 -g -DEBUG_ALPHA and run
745 the testsuite under valgrind control. Hack until the program fits the
746 requirements defined by the testsuite.
748 + Build with desired optimization level and -g -DEBUG_BETA and give the
749 program to your beta testers.
751 + Just build it with optimization and without -g -DEBUG_*
753 What and when to check
755 * Add REQUIRE checks on your interfaces (incoming parameters). Especially if
756 a argument might not cover the whole range of the underlying type.
757 * Don't waste your and your CPU's time with unessesary checks. The testsuite
758 should validate your program. NoBug aids in debugging. You can add
759 Postconditions (ENSURE) and Invariants when you have a bug somewhere and
760 want to nail it down.
761 * Added checks don't need to be removed.
762 * When you use the CHECKED/UNCHECKED features then don't forget C scoping
763 rules, tag things as CHECKED from the leaves to the root.
767 * TRACE(flagname) or TRACE_DBG(flagname) at the begin of every nontrivial
768 function will easily log the progress of your application.
769 * Trying a RELEASE build will abort on certain conditions (known BUG, TODO's,
770 UNCHECKED code), you can use this to find these spots.
772 This Documentation is maintained at:
774 * http://www.pipapo.org/pipawiki/NoBug/Documentation
776 NoBug/Documentation (last edited 2007-03-26 14:51:39 by ct)