must call INIT before first TRACE
[nobug.git] / README
blob2164cea557b385f5b9173d6f4111a07c8d31c0b1
1 NOBUG Documentation
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.
8 Overview
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
23     detecting misuse.
25 Building and Installing
27 Release Tarballs
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
34 the signature
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
39 validated.
41 Since they are built with gnu autotools, the usual build and install procedure
42 works:
44 $ tar xzvf nobug-X.Y.tar.gz
45 $ cd nobug-X.Y
46 $ ./configure
47 $ make
48 $ make install
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
57 $ autoreconf -i
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
63 ChangeLog.
65 What gets installed
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.
74 Using NoBug
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/
83 valgrind.h
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
91 available.
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
101 useful.
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/
107 MultiThreading.
109 Debug Control
111 Build Levels
113 Nobug uses the following different levels of checks:
115   * ALPHA
116       + for expensive testing and logging while developing the software
117     BETA
118       + for testers and users who want to try the software
119     RELEASE
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.
133 Scope Checks
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
137 not allowed.
139 Test Matrix
141 Here is a table of which basic assertions gets checked on each level/scope
142 combination:
144           ALPHA                          BETA                   RELEASE
145 UNCHECKED Preconditions, Postconditions, Preconditions,         compiling will
146           Invariants                     Postconditions         abort
147 CHECKED   Preconditions, Postconditions  Preconditions
149 Macros
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.
173 Parameters types:
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,
179         only its arguments
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
183 lvl     Log level
184 depth   Depth for invariants and dumps
186 Initialization
188 Global init
190 You have to call
192   * NOBUG_INIT
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
197 won't interfere.
199 Control Flags
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.
214 Threads
216 In Multithreaded programs you should assign an identifier to each thread after
217 it is created with
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.
224 Assertions
226   * REQUIRE(expr, ...)
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.
231     ENSURE(expr, ...)
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.
238     ASSERT(expr, ...)
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.
246     assert(expr)
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)
256 Logging
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:
264   * RINGBUFFER
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.
268   * CONSOLE
269       + This is either just stderr or if running under valgrind then valgrind
270         facilities to include messages into its log will be used.
271   * FILE
272       + The user can open Files for log messages.
273   * SYSLOG
274       + Messages are send to the standard system logging daemon.
275   * APPLICATION
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
280 messages do.
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.
289 Configuration
291 Log Levels
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
295 defined limit.
297 The defaults look like:
299             ALPHA BETA    RELEASE
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
318     NOBUG_TARGET_CONSOLE
319   * In BETA builds, NOBUG_LOG_TARGET_BETA is used and defaults to
320     NOBUG_TARGET_FILE
321   * In RELEASE builds, NOBUG_LOG_TARGET_RELEASE is used and defaults to
322     NOBUG_TARGET_SYSLOG
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
326 defaults.
328 Log Flags
330 Flags are used to tell NoBug about subsystems/modules or even finer grained
331 parts of the code.
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
349 Next you should call
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
386 redefined in future.
388 <!> NOTE: '(options)' on targets are not yet implemented!
390 Examples:
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.
399 Example code:
401    1 #include "nobug.h"
402    2 NOBUG_DEFINE_FLAG (test);
403    3
404    4 int
405    5 main()
406    6 {
407    7   NOBUG_INIT_FLAG (test);
408    8
409    9   INFO (test, "Logging enabled");
410   10   INFO (NOBUG_ON, "Always on");
411   11 }
413 test it:
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
422 The Logging Macros
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
426 debugging library.
428   * ERROR(flag, fmt, ...)
429     ERROR_IF(expr, rflag, fmt, ...)
430       + Application takes a error handling brach
432     WARN(flag, fmt, ...)
433     WARN_IF(expr, flag, fmt, ...)
434       + Rare, handled but unexpected branch
436     INFO(flag, fmt, ...)
437     INFO_IF(expr, flag, fmt, ...)
438       + Message about program progress
440     NOTICE(flag, fmt, ...)
441     NOTICE_IF(expr, flag, fmt, ...)
442       + More detailed
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
464 if you have a
466    1 struct STRUCTNAME
467    2 {
468    3   int INTEGER_MEMBER;
469    4   char * STRING_MEMBER;
470    5   struct STRUCTNAME* next;
471    6 }
473 then you define a function like:
475    1 void
476    2 nobug_STRUCTNAME_dump (const struct STRUCTNAME* self,
477    3                        const int depth,
478    4                        const char* file,
479    5                        const int line,
480    6                        const char* func)
481    7 {
482    8   // check for self != NULL and that the depth
483    9   // limit did not exceed in recursive datastructures
484   10   if (self && depth)
485   11   {
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);
492   18   }
493   19 }
495 now you can use the DUMP() macros within the code
497    1 example()
498    2 {
499    3   struct STRUCTNAME foo;
500    4   init(&foo);
501    5   DUMP (my_flag, STRUCTNAME, &foo, 2);
502    6 }
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.
508 Source Annotations
510 One can tagging features as:
512   * DEPRECATED(...)
513       + Something which shouldn't be used in future.
514     UNIMPLEMENTED(...)
515       + important, not yet finished feature
516     PLANNED(...)
517       + planned for future feature
518     FIXME(...)
519       + known bug to be fixed later
520     TODO(...)
521       + enhancement to be done soon
522     NOTREACHED
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:
531               ALPHA BETA         RELEASE
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
539 Legend:
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
547 Resource Tracking
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.
556 Concepts
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
561 NoBug facilities.
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.
572 The macros
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
613     looked up.
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
660 shown on dumps.
662 Just a simple example:
664    1 void example()
665    2 {
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");
669    6
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
675   12
676   13   // program does something useful here
677   14
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
680   17
681   18
682   19   // back in the main thread
683   20   RESOURCE_FORGET_NAME("mutex", "my_mutex");               // remove the resource from the public registry
684   21 }
686 Notes
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.
702 Multithreading
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
709 programs.
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.
730 Tool Macros
732   * BACKTRACE(...)
733       + Log a stacktrace
734     ABORT
735       + just calls abort()
737 Best Practices
739 <!> this section is very work in progress
741 Workflow
743  1. Development
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.
747  2. Beta Test
748       + Build with desired optimization level and -g -DEBUG_BETA and give the
749         program to your beta testers.
750  3. Release
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.
765 Tips & Tricks
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)