5 Everyone makes errors, but with NoBug you won't make them twice!
7 Nobug is a simple debugging library for instrumenting C and C++ programs
8 inspired by ideas originating from Design-by-Contract.
13 The following features are provided by NoBug:
15 * Three different check levels: from detailed to final no-overhead
16 * Scope tags: tell whenever a function or loop is considered to be bug free
17 * Precondition, Postcondition and Invariant checks and generic assertions
18 * Debugger support (actions are only executed while running under a
19 debugger), currently only valgrind is supported
20 * Datastructures can be dumped
21 * Application activities can be logged
22 * Runtime customizable logging via an environment variable
23 * Different logging targets to stderr, syslog, debugger, ...
24 * Annotation of your sourcecode about known bugs, things to do, etc.
25 * Tracking resources (files, locks, etc.) used by your program; help in
29 In contrast to traditional debuggers, NoBug is a non-interactive debugger which
30 is linked to your application doing hard-coded tests in an efficient,
33 Building and Installing
34 -----------------------
39 Release tarballs are attached to this wiki at:
41 * http://pipawiki/NoBug?action=AttachFile
43 Gpg signed tarballs are being used for distribution. The first step involves
44 checking the signature:
46 $ gpg nobug-X.Y.tar.gz.gpg
48 This will produce a nobug-X.Y.tar.gz and report if the signature could be
51 Since they are built with gnu autotools, the usual build and install procedure
54 $ tar xzvf nobug-X.Y.tar.gz
60 Development Version via git
61 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
63 The development version is available via git from 'git://git.pipapo.org/nobug'
64 or mirrored at repo.or.cz 'git://repo.or.cz/nobug.git'.
66 After you have cloned the repository, you'll then have to bootstrap the
71 Then the usual ./configure && make && make install will work.
73 There is a special makefile target make meta to bring several files (README,
74 AUTHORS, NEWS) in sync with the NoBug documentation wiki and update the
80 Currently, NoBug installs the following:
82 * A single nobug.h headerfile which your code will use
83 * Two libs that are used by statically linking:
84 + 'libnobug.a' for singlethreaded programs.
85 + 'libnobugmt.a' for multithreaded programs.
90 You can make NoBug features available either by installing it as described
91 above or by shipping the nobug sources along with your project.
93 To use NoBug, some controlling preprocessor macros have to be defined. The
94 nobug.h header should then be included.
96 A project using NoBug should use autoconf to check for execinfo.h and valgrind/
99 AC_CHECK_HEADERS([execinfo.h valgrind/valgrind.h])
101 For Multithreaded programs, you should also check for pthread.h.
103 When the resulting HAVE_PTHREAD_H, HAVE_EXECINFO_H and HAVE_VALGRIND_VALGRIND_H
104 are defined by the configure script, the corresponding features become
107 NoBug then defines 'NOBUG_USE_PTHREAD', 'NOBUG_USE_VALGRIND' and
108 'NOBUG_USE_EXECINFO' to 1. If you do not want to use any of these features in
109 NoBug, you can define these macros to 0 before including nobug.h.
111 If NVALGRIND is defined, valgrind support will not be available.
113 There are many other macros which can be set and overridden by the user to
114 control behavior. Please edit the wiki documentation if you find them useful.
116 To use NoBug with single threaded programmes, link libnobug.a to your project;
117 multi-threaded programmes should link with libnobugmt.a. The Library must be
118 initialized with NOBUG_INIT before any features can be used or a thread is
119 created. This is discussed in more detail at NoBug/Documentation/Macros/
122 Header and Initialisation
123 ^^^^^^^^^^^^^^^^^^^^^^^^^
124 The project source file will have to include nobug.h, and Nobug will have to be
125 initialised using NOBUG_INIT before any NoBug features can be used.
127 -------------------------------------------------------
137 -------------------------------------------------------
138 Checking for Additional Tools
139 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
140 NoBug uses a number of additional optional tools depending on the application
141 and the debugging information required. Such tools as valgrind, gdb and support
142 for multi-threaded applications can be tested whether they are available on a
143 particular system. This can be done, for example, by using autoconf.
145 Depending on the value of the following defines, the relevant tool or feature
150 0;; Do not use valgrind
153 1;; Support for multi-thread applications
154 0;; Single-threaded applications
157 1;; Backtrace information
158 0;; No backtrace informatin
160 Debugging Information Granuality: The Build Levels
161 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
162 Debugging information can be produced at three different levels: alpha, beta and
166 This debugging level is envisaged for the development phase of a project
167 where exhaustive testing and logging are requred.
169 This debugging level is more appropriate for projects beyond the
170 development phase and ready for trials in the field and users willing to
173 This level is for final, end-users.
178 One of the above debugging levels is selected by defining one of the following:
180 *ALPHA*:: -DEBUG_ALPHA
186 Then the project is compiled. If one of the above switches has not been set,
189 Link Appropriate Library
190 ^^^^^^^^^^^^^^^^^^^^^^^^
191 Finally, the appropriate library (for either single or multi-threaded
192 applications) is linked to the project.
194 *libnobug.a*:: Link-in this library for single threaded applications.
195 *libnobugmt.a*:: Link with this library for multi-threaded applications.
198 Release builds remove all assertions, but some logging is still kept. We make
199 the assumption that bugs which were not covered in alpha and beta builds will
200 not easily show up in releases because the assertions there were not
201 sufficient. Furthermore, end users are not test bunnies and will not provide
202 good bug reports anyway. If there is a problem in a release build, try to track
203 down the cause using a beta build from the same source.
208 The programmer can tag any scope as UNCHECKED or CHECKED. In ALPHA and BETA
209 builds, a global UNCHECKED is implied. In RELEASE builds, UNCHECKED scopes are
214 Here is a table of the basic assertions that are checked depending on the level
218 UNCHECKED Preconditions, Postconditions, Preconditions, compiling will
219 Invariants Postconditions abort
220 CHECKED Preconditions, Postconditions Preconditions
224 The NoBug interface is almost completely implemented using preprocessor macros.
225 This is required because NoBug uses the __FILE__ and __LINE__ macros to log
226 information on the current file and the current line number within that file.
227 Moreover, all the flat namespace uppercase identifiers make it ease to
228 recognise the macros in source code.
230 All macros are available without condition with the 'NOBUG' prefix. Macros are
231 also available without the NOBUG prefix as a convenience, however macros
232 without this prefix must not have been previously defined. All assertion and
233 logging macros have a corresponding form postfixed by '_DBG'. Such macros will
234 only be active within a debugger and are only available in ALPHA builds.
236 When NOBUG_DISABLE_SHORTNAMES is defined by the user, then only the NOBUG_
237 prefixed macros are available and the short forms will never be defined.
239 A set of macros are provided by NoBug that are postfixed by '_IF'. These macros
240 are wrappers around assert from the C lib. These macros have the following
243 * WHATEVER_IF(when, ...)
245 We assert that when is true, if it is not, the assertion will fail. For
248 * REQUIRE_IF(foo!=NULL, foo->something == constrained)
250 The assertion will only be performed if foo points to some memory, or is non
253 Debugger versions are available using _IF_DBG postfixed to the name of the
258 when Assertion is only performed if expression 'when' is true at runtime
259 expr Test without side effects
260 fmt printf-like format string
261 ... If not preceded by 'fmt', then printf-like format string; otherwise,
263 flag Flag to enable custom logging groups
264 type Data type to be checked as a single identifier name
265 pointer Pointer to type
267 depth Depth for invariants and dumps
277 before using any other NoBug feature. Probably in main or any other library
278 initialization routine. Calling NOBUG_INIT more than once is supported and each
279 subsequent call will be a no-op, thus initialization in main and in libraries
284 If you want to use environment variable controlled debuging, then you have to
285 initialize each flag with
287 * NOBUG_INIT_FLAG(flagname)
291 * NOBUG_INIT_FLAG_LIMIT(flagname, default)
293 This is documented later in NoBug/Documentation/Macros/LoggingConfiguration.
295 * <!> These two macros call NOBUG_INIT for backward compatibility.
299 In Multithreaded programs you should assign an identifier to each thread after
302 * NOBUG_THREAD_ID_SET(name)
304 If you don't call it, then NoBug will assign a automatic identifier. This is
305 documented in NoBug/Documentation/Macros/MultiThreading.
310 + Precondition (input) check. Use these macros to validate input a
311 function receives. The checks are enabled in ALPHA and BETA builds and
312 optimized out in RELEASE builds.
315 + Postcondition (progress/output) check. Use these macros to validate the
316 data a function produces (example: return value). The checks enabled
317 unconditionally in ALPHA builds and optimized out in BETA builds for
318 scopes which are tagged as CHECKED. In RELEASE builds this checks are
319 always optimized out, but scopes tagged as UNCHECKED are not permitted.
322 + Generic check. Use these macros when you want to validate something
323 which doesn't fall into one of the above categories. A example is when
324 a library function can return a unexpected result (scanf with syntax
325 error in the formatstring, when a constant/literal formatstring is
326 expected). The checks are enabled in ALPHA and BETA builds and
327 optimized out in RELEASE builds.
330 + NoBug overrides the standard assert macro in ALPHA and BETA builds.
331 This is just a compatibility feature, its use is not suggested.
333 INVARIANT(type, pointer, depth)
334 + Checking invariants. You can provide more complex checking functions
335 which test the validity of datastructures. Invariants are only enabled
336 in ALPHA builds for scopes which are not tagged as CHECKED and
337 otherwise optimized out. (TODO: document how to write invariants)
341 Nearly all NoBug Macros emit some log message. NoBug gives the user fine
342 grained control over these log messages to display only interesting information
343 without loosing details.
345 Log messages are routed to different destinations which are:
348 + The underlying storage backend. Messages are appended to the end of the
349 buffer, overwriting older messages at the front of the buffer. NoBug
350 comes with a highly efficient ringbuffer implementation. This
351 ringbuffer is temporary by default but can be made persistent. NoBug
352 comes with a 'nobug_rbdump' tool to get a log out of such a ringbuffer.
354 + This is either just stderr or if running under valgrind then valgrind
355 facilities to include messages into its log will be used.
357 + The user can open Files for log messages.
359 + Messages are send to the standard system logging daemon.
361 + There is a hook which allows the programmer to catch logmessages and
362 display them in a application defined way.
364 Each logmessage has a priority describing its severity in the same way as
367 All non-fatal messages are associated with a programmer defined flag describing
368 the source of the message (subsystem, module, ...).
370 Putting it all together: A user can define which source/flag shall be logged at
371 what priority level and to which destination. To make this all easier NoBug
372 tries to give reasonable defaults.
378 Each Log macro has a explicit or implicit Log-Level which correspondends to
379 syslog levels. Logging is only emitted when the messages is more severe than a
382 The defaults look like:
385 ringbuffer TRACE INFO NOTICE ringbuffer must always be most verbose
386 console INFO NOTICE -1 no log to console in release
387 file TRACE NOTICE WARNING
388 syslog -1 NOTICE WARNING no syslog for test runs
389 application INFO WARNING ERROR
391 Depending on the build level there is a default logging target and a default
392 limit which is choosen when the user doesn't specify one.
394 The default limits are:
396 * In ALPHA builds, NOBUG_LOG_LIMIT_ALPHA is used which defaults to LOG_INFO
397 * In BETA builds, NOBUG_LOG_LIMIT_BETA is used and defaults to LOG_WARNING
398 * In RELEASE builds, NOBUG_LOG_LIMIT_RELEASE is used and defaults to LOG_CRIT
400 The default targets are:
402 * In ALPHA builds, NOBUG_LOG_TARGET_ALPHA is used which defaults to
404 * In BETA builds, NOBUG_LOG_TARGET_BETA is used and defaults to
406 * In RELEASE builds, NOBUG_LOG_TARGET_RELEASE is used and defaults to
409 You can override all of those values with your own preference. Alternatively
410 NOBUG_LOG_LIMIT and NOBUG_LOG_TARGET can be defined by the user to override all
415 Flags are used to tell NoBug about subsystems/modules or even finer grained
418 A Flag should be declared with
420 * NOBUG_DECLARE_FLAG(flagname)
422 preferably in one of your headers
424 Further it must be defined with
426 * NOBUG_DEFINE_FLAG(flagname)
430 * NOBUG_DEFINE_FLAG_LIMIT(flagname, limit)
432 in one of your source files
434 There are also macros which take a 'parent' flag as parameter which is then
435 used to initialize the defaults from another flag
437 * NOBUG_DEFINE_FLAG_PARENT(flagname, parent)
441 * NOBUG_DEFINE_FLAG_PARENT_LIMIT(flagname, parent, limit)
443 This can be used to create hierachies of flags
447 * NOBUG_INIT_FLAG(flagname)
451 * NOBUG_INIT_FLAG_LIMIT(flagname, default)
453 once at the start of your program for every flag.
455 For flags defined with NOBUG_DEFINE_FLAG(flagname) the defaults are initialized
456 as in the table above, while NOBUG_DEFINE_FLAG_LIMIT(flagname, level) is used
457 to initialize the default target (depending on build level) to limit. Calling
458 NOBUG_INIT_FLAG(flagname) is optional for limit initialized flags.
460 NOBUG_INIT_FLAG(flagname) parses the environment variable '$NOBUG_LOG' for
461 flagname, the syntax is as following:
463 logdecl_list --> logdecl, any( ',' logdecl_list).
465 logdecl --> flag, opt(limitdecl, any(targetdecl))
467 flag --> "identifier of a flag"
469 limitdecl --> ':', "LIMITNAME"
471 targetdecl --> '@', "targetname", opt(targetopts)
473 targetopts --> '(', "options for target", ')', opt(targetopts)
475 Roughly speaking, NOBUG_LOG contains a comma separated list of declarations for
476 flags which are the name of the flag followed by a limit which is written in
477 all uppercase letters and preceeded by a colon, followed by target declarations
478 which are names of the targets, introduced by a at sign. Target declarations
479 can have options in future which is not yet implemented. Limit and target
480 declarations are optional and then choosen from the defaults table above. These
481 defaults are currently just an guess what should be useable and might be
486 The Following options are implemented:
489 + (file=filename) set filename backing the ringbuffer
490 (size=nnn) set size of the ringbuffer
491 (append) don't erase existing ringbuffer
492 (keep) keep file after application end
493 (temp) unlink file instantly at creation
496 + (fd=n) redirect console output to fd n
499 + (name=filename) log to filename
500 (append) append to (existing) log
503 + (ident=name) global prefix for syslog
504 (cons) log to system console if syslog is down
505 (pid) include pid in log
506 (perror) log to stderr as well
510 NOBUG_LOG='flag,other' # set the limit of the default target a default limit (see table above)
511 NOBUG_LOG='flag:DEBUG' # set the limit of the default target to DEBUG
512 NOBUG_LOG='flag:DEBUG@console@syslog' # set console and syslog limits for flag to DEBUG
513 NOBUG_LOG='flag:DEBUG,other:TRACE@ringbuffer(file=log.rb)(size=8192)(keep)' # trace 'other' to a persistent ringbuffer
515 There is a predefined flag NOBUG_ON which is always enabled.
520 2 NOBUG_DEFINE_FLAG (test);
525 7 NOBUG_INIT_FLAG (test);
527 9 INFO (test, "Logging enabled");
528 10 INFO (NOBUG_ON, "Always on");
533 $ tcc -DEBUG_ALPHA -run example.c
534 example.c:10: debug: INFO: main: Always on
536 $ NOBUG_LOG=test tcc -DEBUG_ALPHA -run example.c
537 example.c:9: debug: INFO: main: Logging enabled
538 example.c:10: debug: INFO: main: Always on
542 When used in C++ programms the following additional marocs are available:
544 * NOBUG_CPP_DEFINE_FLAG(name)
545 NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent)
546 NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default)
547 NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default)
549 This macros statically initialize the flags at definition time, there is no
550 need to call NOBUG_INIT_FLAG().
554 These macros log with implicit Log Level, note that there are no more severe
555 levels than LOG_ERROR since these should be handled by Assertions in a
558 * ERROR(flag, fmt, ...)
559 ERROR_IF(expr, rflag, fmt, ...)
560 + Application takes a error handling brach
563 WARN_IF(expr, flag, fmt, ...)
564 + Rare, handled but unexpected branch
567 INFO_IF(expr, flag, fmt, ...)
568 + Message about program progress
570 NOTICE(flag, fmt, ...)
571 NOTICE_IF(expr, flag, fmt, ...)
574 TRACE(flag, fmt, ...)
575 TRACE_IF(expr, flag, fmt, ...)
576 + Very fine grained messages
578 Note that TRACE corresponds to LOG_DEBUG, using 'DEBUG' could be ambiguous.
580 There is one generic LOG macro which takes the level explicitly:
582 * LOG(flag, lvl, fmt, ...)
583 LOG_IF(expr, flag, lvl, fmt, ...)
585 Dumping Datastructures
587 * DUMP(flag, type, pointer, depth)
588 + Dump a datastructure
589 DUMP_IF(expr, flag, type, pointer, depth)
590 + Dump datastructure if expr is true
592 How to write DUMP handlers
598 3 int INTEGER_MEMBER;
599 4 char * STRING_MEMBER;
600 5 struct STRUCTNAME* next;
603 then you define a function like:
606 2 nobug_STRUCTNAME_dump (const struct STRUCTNAME* self,
612 10 if (self && depth)
614 13 DUMP_LOG("STRUCTNAME %p: int is %d, string is %s", self,
615 14 self->INTEGER_MEMBER,
616 15 self->STRING_MEMBER);
617 17 nobug_STRUCTNAME_dump (self->next, depth-1, file, line, func);
621 now you can use the DUMP() macros within the code
625 3 struct STRUCTNAME foo;
627 5 DUMP (my_flag, STRUCTNAME, &foo, 2);
630 Dumping is by default done on level LOG_DEBUG, this can be overridden by
631 defining NOBUG_DUMP_LEVEL to some other level, further DUMP_IF is the only
632 enabled dumping macro for the RELEASE build level.
637 One can tagging features as:
640 + Something which shouldn't be used in future.
642 + important, not yet finished feature
644 + planned for future feature
646 + known bug to be fixed later
648 + enhancement to be done soon
650 + used to tag code-path which shall be never executed (defaults in switch
651 statements, else NOTREACHED after series of if's)
653 The advantage of this tagging over plain source comments is that we can take
654 some actions if we run in such a tag at compile or runtime:
656 the action to be taken when such a macro is hit depends on the build level:
659 DEPRECATED log nothing wont compile
660 UNIMPLEMENTED abort abort wont compile
661 FIXME log wont compile wont compile
662 TODO log log wont compile
663 PLANNED log nothing nothing
664 NOTREACHED abort abort removed
668 * abort means first log and then abort
669 * log will only log once for each sourceline (not on each hit)
670 * wont compile will abort compilation with a error message
671 * nothing optimized out, sane way
672 * removed optimized out for performance reasons
676 With little effort, NoBug can watch all kinds of resources a program uses. This
677 becomes useful for resources which are distributed over a multithreaded
678 program. Resource tracking is only active in ALPHA builds and optimized out in
679 BETA and RELEASE builds.
683 Resources are abstracted, NoBug has little knowledge about the semantics of a
684 resource, it only keeps records of resources and the code using it and ensures
685 basic constraints. Detailed usage checks of resource have to be done with other
688 Resources are identified by a arbitrary identifier which is just a pointer and
689 if using threads, NoBug's thread identifier. Additionally a name, the type and
690 the source locations which announced the resource are stored.
692 Code which wants to use a resource calls a enter macro with its own identifier
693 and state, then might alter the state and finally a leave macro when finished
696 When a resource is used one has to pass one of three states:
698 * NOBUG_RESOURCE_WAITING
699 + For resources where acquisition could block (locks) you enter it with a
700 WAITING state and as soon you aacquired it you change the state to one
702 * NOBUG_RESOURCE_EXCLUSIVE
703 + Acquired the resource exclusively, this means for NoBug that trying to
704 get the resource again with the same identifier would be fatal, other
705 parts of the program could still enter it.
706 * NOBUG_RESOURCE_RECURSIVE
707 + The resource might be entered multiple times from the same identifier,
708 NoBug keeps a reference count and only deletes the record when the
709 resource is left as much times the state was changed to
710 NOBUG_RESOURCE_RECURSIVE
712 Possible state transitions:
718 Resources are accessed through handles, these handles are defined with
720 * RESOURCE_HANDLE(name)
722 This macro takes care that the declaration is optimized out in the same manner
723 the rest of the resource tracker would be disabled. You can still instantiate
724 handles as struct nobug_resource_record* in structures which must have a
725 constant size unconditional of the build level.
727 Resources are published by
729 * RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
731 Resources must be unique, it is a fatal error when a resource it tried to be
732 announced more than one time.
734 * 'flag' is nobug flag which turns logging on for this macro.
735 * 'type' is a cstring which should denote the domain of the resource,
736 examples are "file" "mutex" "lock" "database" and so on.
737 * 'name' is the actual name of a named resource this is a cstring which
738 together with type forms a unique identifier of the resource. 'type' and
739 'name' must be available through the entire lifetime of the resource, using
740 literal strings is recommended.
741 * 'identifier' is a pointer which should be unique for this resource, any
742 kind of pointer will suffice, it is only used for identification. In
743 multithreaded applications the thread identifier becomes an additional
745 * 'handle' is a nobug_resource_record* which will be initialized to point to
746 the newly created resource.
748 When a resource becomes unavailable it is removed from the registry by
750 * RESOURCE_FORGET(flag, handle)
752 The resource must still exist and no users must be attached to it, else a fatal
755 Code which wants to use a resource attaches to it by
757 * RESOURCE_ENTER(flag, announced, name, identifier, state, handle)
758 * 'flag' is nobug flag which turns logging on for this macro.
759 * 'announced' is the handle set by RESOURCE_ANNOUNCE
760 * 'name' is a free-form identifier
761 * 'identifier' is some pointer which must be unique for the user of the
763 * 'state' is the initial state, one of NOBUG_RESOURCE_WAITING,
764 NOBUG_RESOURCE_EXCLUSIVE or NOBUG_RESOURCE_RECURSIVE
765 * 'handle' is a nobug_resource_record* which will be initialized to the
768 For some uses one can change the state with
770 * NOBUG_RESOURCE_STATE(flag, entered, state)
771 * 'flag' is nobug flag which turns logging on for this macro.
772 * 'entered' is the handle set by RESOURCE_ENTER
773 * 'state' is the new state Note that only certain state transitions are
774 allowed, see discussion/diagram above
776 When finished with using the resource you disconnect from it either with the
777 handle you initialized when entering it
779 * RESOURCE_LEAVE(flag, handle)
780 * 'flag' is nobug flag which turns logging on for this macro.
781 * 'handle' is the handle you got while entering the resource.
783 or by looking it up in the announced resource by its identifier
785 * RESOURCE_LEAVE_LOOKUP(flag, resource, identifier)
786 * 'flag' is nobug flag which turns logging on for this macro.
787 * 'resource' is the handle you got from announcing the resource.
788 * 'identifier' is the pointer you gave it when creating it
790 Resources keep track of the thread which used them, you cant ANNOUNCE/FORGET
791 ENTER/LEAVE the same handle from different threads.
793 Just a simple example:
795 1 NOBUG_DEFINE_FLAG_LIMIT(test, LOG_DEBUG);
800 7 pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
801 8 RESOURCE_HANDLE(resource)
802 10 RESOURCE_ANNOUNCE(test, "mutex", "my_mutex", example, resource);
804 14 RESOURCE_ENTER_NAME(test, resource, "example", &enter, NOBUG_RESOURCE_WAITING, enter);
813 The Resource Tracker is able to detect potential deadlocks. This is done by
814 learning the relations between locks (precedence). A possible deadlock results
815 in a log message and a fatal abort. Note that only waiting on resources can
816 lead to a deadlock. Deadlock detection is implemented in the Resource Tracker
817 and active in ALPHA builds.
821 Unless the user defines NOBUG_RESOURCE_LOGGING to 0 each of the above macros
822 will emit a log message at NOBUG_RESOURCE_LOG_LEVEL which defaults to
827 The Resource Tracker is neither bullet-proof nor exact. There are small race
828 conditions in the time we announce/forget/enter/remove resources and doing the
829 actual call to a resource. These race conditions affect the reporting exactness
830 and are a design decision, for there is no danger for practical use.
832 More important is that the Resource Tracker relies on that announce/forget and
833 enter/leave are properly paired. The programmer should ensure that this is done
834 right, else it will become unusable. This will be addressed in future NoBug
837 The underlying resource-tracking library may report errors, all these errors
838 are fatal for NoBug and trigger an abort(). When such an error occurs the
839 Resource Tracker is left in a locked state, which is harmless and intended for
840 generating reports prior the abort.
844 It is important that NoBug protects certain operations with locks in
845 multithreaded programs. You have to ensure that 'HAVE_PTHREAD_H' is defined by
846 the configuration system and use the 'libnobugmt.a' library for linking. It is
847 particular important that libraries using NoBug are compiled with
848 'HAVE_PTHREAD_H' enabled when they are intended to be used in multithreaded
851 When Multithreading is used, log messages contain a identifier of the
852 originating thread. This identifier should be set by
854 * NOBUG_THREAD_ID_SET(name)
856 right after thread creation. name is a string describing the purpose of the
857 thread. Nobug will assemble a unique identifier by appending a underscore and a
858 number to name, for example NOBUG_THREAD_ID_SET("gui") will result in a
859 identifier like "gui_5". When you don't set a thread identifier, then NoBug
860 assigns one automatically with the name 'thread' preprended if needed. Thread
861 identifiers are immutable once set.
863 For querying the thread identifier you use
865 * NOBUG_THREAD_ID_GET
867 which will return a const char* to the thread id in multithreaded programs and
868 a pointer to a literal "" in singlethreaded programs.
880 <!> this section is very work in progress
885 + Write a testsuite, build your program with -O0 -g -DEBUG_ALPHA and run
886 the testsuite under valgrind control. Hack until the program fits the
887 requirements defined by the testsuite.
889 + Build with desired optimization level and -g -DEBUG_BETA and give the
890 program to your beta testers.
892 + Just build it with optimization and without -g -DEBUG_*
894 What and when to check
896 * Add REQUIRE checks on your interfaces (incoming parameters). Especially if
897 a argument might not cover the whole range of the underlying type.
898 * Don't waste your and your CPU's time with unnecessary checks. The testsuite
899 should validate your program. NoBug aids in debugging. You can add
900 Postconditions (ENSURE) and Invariants when you have a bug somewhere and
901 want to nail it down.
902 * Added checks don't need to be removed.
903 * When you use the CHECKED/UNCHECKED features then don't forget C scoping
904 rules, tag things as CHECKED from the leaves to the root.
908 * TRACE(flagname) or TRACE_DBG(flagname) at the begin of every nontrivial
909 function will easily log the progress of your application.
910 * Trying a RELEASE build will abort on certain conditions (known BUG, TODO's,
911 UNCHECKED code), you can use this to find these spots.