Another approach to debugging does not require you to modify your original C, Pascal, or Fortran source codes. Instead, you use a debugger to provide you with an environment to selectively execute just parts of your program, to print out selected variables when desired, and to trace through variables as they change while your program runs. The dbx debugger does this for you. On the one hand, dbx is a source level debugger. This means that even though it is running your object code, it is smart enough to direct you to the statement in your source which has caused the problem in your object code. On the other hand, dbx is also a symbolic debugger, which means it is smart enough to tell you the name and value of the variable at which your program is having its difficulties and not just the binary value of the location in memory where something is amiss.
In order to use these types of debuggers you must first compile your entire program with the -g option invoked. The compiler then produces the global variable tables needed by the debuggers to convert addresses located in virtual memory to the name of the source subprogram and the line number within that subprogram. While this information is usually provided by default (that is, without explicitly invoking -g option), explicitly invoking the -g permits tracing back to your program's variables, data, and structures. If your executable, or even a subroutine within your executable, is not compiled with the -g option, or if symbol references are removed with the strip command, the symbolic capabilities of dbx are limited. Furthermore, if you are using C or Fortran preprocessors, such as cpp, ratfor, or elf, you may want to generate and save the intermediate (.i, .f) files since they provide information to help dbx find the bugs.
Optimization and debugging have conflicting approaches to processing your program, so you should run the debugger on nonoptimized code only. After the bugs are removed, you continue to leave the debugging option on as you increase the level of optimization. Finally, when the program enters the production stage, turn off all storage of global symbol tables. The exception to this rule occurs when the bug occurs only at higher optimization levels, in which case you may as well try the debugger with your optimized but buggy code.
Some of the subcommands given from within dbx (when you see the (dbx) prompt) include:
There are more subcommands available for use with dbx. If you use the X Windows interface xde, many subcommands as well as needed documentation are available via pull-down menus and buttons. We recommend it! As your programs get more complicated or your problems more subtle, you may need to check the man pages for details. For example, if your program has a fault which keeps it from executing and causes a core dump to be produced, dbx can examine the state of the program when it faulted, something we mere mortals dare not do.