BOBO dHHHHHH2 H(,.  2-ZPerry The CynicfBLOM!`xxHHLXG(HH(d'` Dl /c   1lcHt  <4[w] DSET,o'0,o Z0`211 ($*u  0)1N d/k" <#@).?j<zQ % K O    .  V (Vq"1*Yy % !!,!I!e!!!!"#a##$%c&t'g'r))#))***T+K,o @       < B  ) K S   . ?    [ b j      < z       c j o w         # Y _         %          (      R  a  b  c    .  3                  R  S  V        > D  s z        (  7 <     = G      : D  ' ,  8 <  n x     3 <  V q      (     % .  > B K  d j        4 =  M O P  W X  g p        Z f              ] a     0 4  }   _ e    )  2  q  {      ! !I ! ! ! !  " ")  ": "@  #a #  # #  # #  #$ $ % % % & & '$ '0 'g'r  ' '  ( (  () (/  ( (  ) )#  )A )M  ) )  ) *T  * *  +Y +b  +o +s  + +  , ,  ,* ,.   aT Rz&1~11 3H 10d2 2R0l R2$R &S2X(p0Debugging Aids (Little Helpers when things go Bump in the Dark) What to do when things go wrong? You debug. Here is some help. The Importance of NDEBUG There is a single preprocessor #define symbol that can, in effect, turn all debugging code off. Its called NDEBUG. Simply add -DNDEBUG to your compiler arguments (CFLAGS) and recompile, and all debugging code you put into your code should go away. Of course, thats the theory. In practice, there are a few rules you should follow, and a few problems you should look out for. Lowercase vs. Uppercase Debug facilities whose names are ALL CAPS are (or could be) macros. Think of those as syntactic constructs, not as function calls. Conversely, debug facilities in lowercase are normal C++ constructs (functions, classes, members, etc.) and will behave as such. The Big Switches Obviously, any code can be removed for production builds by plac~ing it between the usual #if !defined(NDEBUG) ... #endif //NDEBUG This is somewhat ugly and can be hard to read, so use it sparingly. To remove a fairly small portion of code (say, one declaration or statement), use the IFDEBUG macro: IFDEBUG(unsigned int freeSlotCount = 0); If NDEBUG is defined, the argument is ignored; otherwise it is compiled. Note that IFDEBUG does not add a final semicolon, so it is validly used in part of a statement: int getMaxLength(State *state IFDEBUG(, bool verify = false)) will give getMaxLength a second argument only if NDEBUG is undefined. The reverse macro IFNDEBUG is also available, with the obvious reversed meaning. In the end, its up to your judgment as to how far you want to stretch the use of IFDEBUG and IFNDEBUG. At some point, using #if statements becomes more readable. Assertions and Errors The system provides an assert macro with the obvious meaning . Note that this is a macro, not a function we didnt invent its name (sorry). Assert will abort the program if its condition fails: assert(elements->first != NULL); The message generated will give the source location and expression string that failed, so you might as well make the expression as self-explanatory as possible. Within the debugger, to intercept assertions, set a breakpoint on the C function abort. You may want to do this in your .gdbinit file. Generating Debug Messages The simplest application of debug logging is this: #include ... debug(subs, unexpected value %d for %s, theValue, theItemName); The debug function works like printf. Its initial argument is a debug scope, an arbitrary string of up to 12 characters that identifies the subsystem this message belongs to. Compiled with default arguments, this code will log a message to the debug message stream. If compiled with -DNDEBUG, it will do nothing at all (and should generate no code, if the compiler is bright enough). If you want more detailed control, you can use the contents of namespace Debug . Among other things, you can create separate debug scope objects and invoke them for messages: #include Debug::Scope mydebug(subs); mydebug(object %p destroyed, object); Scope objects simply extract the scope identifier string, so you dont have to repeat it with every call to debug. Caveat Note that debug calls are function calls, not macros. Even with NDEBUG defined, arguments to debug may still be evaluated if they have side effects. But then they may not : debug(foo, array extended to %d elements, ++count); is a very bad idea. On a more pedestrian note, complicated functions (particularly involving memory allocators) can exceed the grasp of the optimizer and stay around even with NDEBUG, so you may want to bracket the call with the IFDEBUG macro: IFDEBUG(debug(foo, got %s, module->rep().getName().c_str())); makes sure the complicated expression isnt evaluated in the NDEBUG case. Displaying Debug Messages Just including debug calls in your code will get you nothing by default. You control the contents, destination, and various optional behaviors with environment variables. DEBUGSCOPE: What To Log In order to actually receive messages, you need to set environment variables. The DEBUGSCOPE variable can be set to a comma-separated list of scope strings, such as subs,thread. This causes all debug calls for the subs and thread scopes (and none other) to be displayed. The default (if DEBUGSCOPE is not set) is nothing. If you set DEBUGSCOPE to the special string all, then all scopes are displayed. You can also express all but these scopes by starting the variable with a dash: -thread,mutex will display all scopes except the mutex and thread ones. Note that debug calls with NULL scope strings will generate log messages even if DEBUGSCOPE is undefined or empty (this is an override feature used internally by the debug system). Removing the DEBUGSCOPE variable is thus not a foolproof way to turn all debug messages off. Set DEBUGDEST to /dev/null for that. DEBUGDEST: Where To Put It By default, debug messages go to the standard error of the process logging the message. You can set the DEBUGDEST variable to redirect messages to different destinations. If DEBUGDEST starts with a forward slash (/), it is an absolute filename path and the log goes there (appended, if the file exists). The file is opened in strict append mode, so multiple processes logging to the same file should not cause unseemly scrambling . If DEBUGDEST is of the form LOG_SOMETHING, it is interpreted as a syslog facility code, and the output goes to the system syslog facility. The priority used is always LOG_DEBUG. It is up to you to set up the syslog.conf file to direct log output to wherever you want it. If DEBUGDEST is of the form >&n, with n a decimal number, then output is redirected to file descriptor n of the current process. You are responsible for setting this file descriptor up, presumably from a parent process or really early in your code. If none of the above applies, as a last resort, the value of DEBUGDEST is used as a (relative) filename. Dont rely on this behavior - it may change. DEBUGOPTIONS: More Choices The DEBUGOPTIONS environment variable can be used to specify additional configuration options for debug logging. The format of DEBUGOPTIONS is a comma-separated list of option values. These options and their behavior are partially specific to particular destinations. The scope option prepends scope identifiers to each output line. This is probably a good idea in most cases, since many debug messages assume you know which scope they are for. Of course, if you only display a single scope, this is superfluous. The thread option prepends the identifier of the current thread to each output line. This is helpful when debugging multi-threaded programs. The identifier used is an arbitrary hex string . The pid option prepends the process id of the process being tested. This is useful if you have multiple processes whose debug destinations coincide (because e.g. they share standard error). The date option tells file destinations to include the time-of-day of each message in the log. Resolution is to the nearest second. Note that the syslog demon always adds datestamps to its output, so specifying the date option with a syslog destination will get you duplicate datestamps. The noflush option tells file destinations not to flush the buffers after each log message. This speeds up large debug logs, but may lose you the last few messages if the program crashes hard. Noflush does not apply to the syslog destination, which is always flushed. Some destinations perform locking to ensure that multi-threaded programs do not see debug messages interspersed. In some situations this can cause unpleasant performance hits, and you can turn of this locking with the nolock option. If you do, your output may be mangled a bit. You can add additional options if you write your own logging sink objects (see expert use). Debug Dumps Debug logging is designed for simple, one-line status messages to keep track of what your program is doing (or isnt). If you need to produce voluminous output to dump internal data structures for analysis, debug logging is an inefficient way. Happily, there is also a debug dump facility. The DEBUGDUMP environment variable controls debug dumping the same way that DEBUGSCOPE controls logging. The two settings are independent. Both dumps and logs go to DEBUGDEST and are interspersed. To implement a debug dump, write code like this: #ifdef DEBUGDUMP if (Debug::dumping(acl)) { Debug::dump(%s {, name); for (int n = 0; n < limit; n++) Debug::dump( %s, elem[n].code); Debug::dump(}\n); } #endif DEBUGDUMP Debug::dumping tells you whether dumping a particular scope has been enabled. Debug::dump works just like printf, and can produce partial or multiple line output without restriction. It is usually a good idea to produce a whole set of lines within one section of dump code. To simplify matters, there is a macro IFDUMPING that, somewhat like IFDEBUG, expands to either nothing or its second argument: IFDUMPING(acl, debugDump(object release)); where debugDump would be a function you have defined (under #ifdef DEBUGDUMP) to perform the actual dump. Usage Hints To perform advanced filtering on debug log messages, dump them into a file and use UNIX tools (grep, awk, perl) to analyze them later. If you need to perform online analysis (while the program is running), use a named pipe (man mkfifo), set DEBUGDEST to the pathname of the pipe, and attach a grep/awk/perl script to the pipe to analyze the output. Another, somewhat more elegant approach, is to write a runner tool that creates a pipe, sets DEBUGDEST to >&fileno(p), and forks/executes the test program. This would allow the program to also use other debugging facilities (ptrace etc.) to control the program under test. Avoid using the debug dump facility unless you have a very good reason to output complex, verbose state dumps. The debug dump facility is more complicated and error prone than Debug::debug, and requires more work and maintainance in practice. Expert Use The header file includes additional features for managing debug logging. All debug logging is managed through a Debug::Target object. You can subclass Target to implement your own selection and formatting facility. If you create a subclass of Debug::Target before any debug call is made, it will become the default object used by all debug calls. Use The Source, Luke - or talk to Perry. Output Sinks Actual output is performed by Target::Sink objects. If you have particular output requirements, you can subclass Target::Sink and install your sink object into the target: #include class MySink : public Debug::Target::Sink { ... } Debug::Target::get().to(new MySink(...)); This lets you direct output in any way you like. You can switch output sinks as often as you like; a previously installed sink is automatically deleted by the Target::to method. (This means that your sink objects better be dynamically allocated.) Note that the configure method of a Sink object is passed a configuration string that is usually obtained from the DEBUGOPTIONS environment variable. You can handle any kinds of option strings you like; Target and standard Sink types are tolerant towards option strings they dont recognize. ZNDSETT"`"  <1(0H     !  #1# Assert is defined in .DSETT:`30 <0h    ( Actually, the simple debug function is also in namespace Debug. It is just named in a using statement so it is directly accessible from global namespace. You can still refer to it as Debug::debug if you wish.DSETT` (3(&1H&    10  The C++ standard goes into some detail as to when side-effect bearing expressions may remain validly unevaluated. This makes exciting reading for language lawyers, but is subtle enough that you dont want to get caught in that corner without a fairly good reason.DSETT\`\2  3   ]1 ] Strict append mode doesnt generally work right on NFS file systems. You have been warned.DSETT`3141P3   18 The thread identifier used bears no resemblance to the identifiers that gdb may use, since gdb makes up its own identifiers pretty much from whole cloth.DSET.H3Z 6*ZDSET .H63tZ 6*ZDSUM(Perry The CynicHDNISTYLF<DSTYL22,01@3( 23L V  ;     3 :  P       5       M    %000000 0 0 0 0 0 0!!0%""##0""$$0""%%0""&&0"$''0"$((0"$ ))0"$ **0"$ ++0"$ ,,0"#--0"#..0"%!//0"%%00110002200033000440025500266002 77002 88002 99002 ::001 ;;001 <<003==003%>>??0>>!@@0>> AA0>>!BB0>@"" CC0>@#DD0>@$ EE0>@% FF0>@& GG0>@' HH0>?#( II0>?#) JJ0>A* KK0>A+%LL,MM0LL$-NN0LL.OO0LL/ PP0LN0QQ0LN1RR0LN2SS0LN3TT0LN4UU0LN5VV0LM%: WW0LM%; XX0LO8 YY0LO9 ZZ,[[0ZZ- N\\0ZZ.]]0ZZ<^^0Z\0__0Z\=``0Z\>aa0Z\?bb0Z\@cc0Z[&: dd0Z]Aee Bff0ee'Cgg0ee Dhh0eg $ii0eg %jj0eg &kk0eg 'll0ef(Gmm0ef(Hnn oo8nn pp8nn qq8nn rr8nn ss8nn tt8nn uu8nn vv8nn ww8nn xx8nn yy8nn zz8nn {{)||8{{*}}8{{+~~8{{,8{{-8{{- 8{{-!8{{-"8{{-#8{{-$8{{-%  &8 '8 (8 )8 *8 + .  /,/,6*-) .. I  "   4160  9,9,2/! 0404141 323257155HASH $ ()( ( ( ) ( (ô׌Lô،Z"0Ҵ"<"%8e>n:7(8(QQA,Qv,oQpvqrst u */vTwyxyz,8|QI}v4~555 5 /5 T5 y5 +$'()*+/0 OHPICU, - 06 17 28 39CcJVKW (2 G. 5&y<y:?; H=%B4 $3 35J?> EM>[1#g-D.E/F0GFJ`B/R0S1T2U0YJX&C.K "@ #A $\ %]jkhi*lmHd/Q9a:b1^7_8`DP0f'O% & C 0$C 0(L:Qfeg{hmhiCodjaqit rl tuzoz}Bod}n;8 CHAR3     7"     77"   " ( ' %         .     / * 2 !/  $  '& &  & )&     2  7  3"    *HASH (0,1-4*E+:"&3: ;#D")*  )% * 5   .66F4HL R 0  3$/@219/  7I CELL3 (+'          6x $ x         7E       F  ( s @HASH     ( ) :;,xx13   -  D"# $ % & '*+ 2345 89B !.<*GHC 10A=>?@ /  GRPH3`+G   |HASH      6l RULR1@\& $B@ @    $ $$Hl D h  $Hl D h$Hl@>++ff@~@f T6HASH43 (" " - .@  k-&,'0Q(v)*+0 2,Qh/v /Ty,Qv ! " /# T$ y% 0  h5@@BB ,Bh0H1~ LKUP  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"$NAMEDefault Default SSHeaderBodyFooterFootnoteFootnote Index Bullet Title Section 1 Q & AQQA DefinitionCode ChecklistNumberClassic" Blue Gray 10 Blue Gray 2>ColorfulL 3D Table 1Z 3D Table 2e AccountingnHarvard{LegalDiamondEmphasisFilename CodeLinesWarning Doc ReferenceSubtitle Section 2DFNTM HelveticaGenevaGenevaTimesPalatinoCourierMCROMCROoBlNoBlNBBARBBARMARKMRKS MOBJWMBTETBLXDSUMIiHDNIISTYLIMCROoBlNBBARMARKWMBTETBL