You are likely to be debugging your program for one of the following reasons:
To determine where and why it is crashing. Strategies for locating the cause of a crash include:
Running the program in dbx. dbx reports the location of the crash when it occurs.
Examining the core file and looking at a stack trace. See Examining a Core File and Looking at the Call Stack.
To determine why your program is returning incorrect results. Strategies include:
Setting breakpoints to stop execution so that you can check your program’s state and look at the values of variables. See Setting Breakpoints and Examining Variables.
Stepping through your code one source line at a time to monitor how the program state changes. See Stepping Through Your Program.
To find a memory leak or memory management problem. Runtime checking lets you detect runtime errors such as memory access errors and memory leak errors and enables you to monitor memory usage. See Finding Memory Access Problems and Memory Leaks.
To determine where your program is crashing, you might want to examine the core file, which is the memory image of your program when it crashed. You can use the where command to determine where the program was executing when it dumped core. See where Command.
$ dbx program-name core
or
$ dbx - core
In the following example, the program has crashed with a segmentation fault and dumped core. First, dbx started with the core file loaded. Then, the where command displays a stack trace, which shows that the crash occurred at line 9 of the file foo.c.
% dbx a.out core Reading a.out core file header read successfully Reading ld.so.1 Reading libc.so.1 Reading libdl.so.1 Reading libc_psr.so.1 program terminated by signal SEGV (no mapping at the fault address) Current function is main 9 printf("string ’%s’ is %d characters long\n", msg, strlen(msg)); (dbx) where [1] strlen(0x0, 0x0, 0xff337d24, 0x7efefeff, 0x81010100, 0xff0000), at 0xff2b6dec =>[2] main(argc = 1, argv = 0xffbef39c), line 9 in "foo.c" (dbx)
For more information about debugging core files, see Debugging a Core File. For more information about using the call stack, see Looking at the Call Stack.
A breakpoint is a location in your program where you want the program to stop executing temporarily and give control to dbx. Set breakpoints in areas of your program where you suspect bugs. If your program crashes, determine where the crash occurs and set a breakpoint just before this part of your code.
When your program stops at a breakpoint, you can then examine the state of program and the values of variables. dbx enables you to set many types of breakpoints Using Ctrl+C to Stop a Process.
The simplest type of breakpoint is a stop breakpoint. You can set a stop breakpoint to stop in a function or procedure. For example, to stop when the main function is called:
(dbx) stop in main (2) stop in main
For more information about the stop in command, see Setting Breakpoints and Traces and stop Command.
You can also set a stop breakpoint to stop at a particular line of source code. For example, to stop at line 13 in the source file t.c:
(dbx) stop at t.c:13 (3) stop at “t.c”:13
For more information about the stop at command, see Setting a Breakpoint at a Line of Source Code and stop Command.
You can determine the line at which to stop by using the file command to set the current file and the list command to list the function in which you want to stop. Then use the stop at command to set the breakpoint on the source line:
Oracle Developer Studio
(dbx) file t.c (dbx) list main 10 main(int argc, char *argv[]) 11 { 12 char *msg = "hello world\n"; 13 printit(msg); 14 } (dbx) stop at 13 (4) stop at “t.c”:13
To continue execution of your program after it has stopped at a breakpoint, use the cont command (see Continuing Execution of a Program and cont Command).
To display a list of all current breakpoints, use the status command:
(dbx) status (2) stop in main (3) stop at "t.c":13
Now if you run your program, it stops at the first breakpoint:
(dbx) run ... stopped in main at line 12 in file "t.c" 12 char *msg = "hello world\n";
After you have stopped at a breakpoint, you might want to step through your program one source line at a time while you compare its actual state with the expected state. You can use the step and next commands to do so. Both commands execute one source line of your program, stopping when that line has completed execution. The commands handle source lines that contain function calls differently: the step command steps into the function, while the next command steps over the function.
The step up command continues execution until the current function returns control to the function that called it.
The step to command attempts to step into a specified function in the current source line, or if no function is specified, into the last function called as determined by the assembly code for the current source line.
Some functions, notably library functions such as printf, might not have been compiled with the -g option, so dbx cannot step into them. In such cases, step and next perform similarly.
The following example shows the use of the step and next commands as well as the breakpoint set in Setting Breakpoints.
(dbx) stop at 13 (3) stop at "t.c":13 (dbx) run Running: a.out stopped in main at line 13 in file "t.c" 13 printit(msg); (dbx) next Hello world stopped in main at line 14 in file "t.c" 14 } (dbx) run Running: a.out stopped in main at line 13 in file "t.c" 13 printit(msg); (dbx) step stopped in printit at line 6 in file "t.c" 6 printf("%s\n", msg); (dbx) step up Hello world printit returns stopped in main at line 13 in file "t.c" 13 printit(msg); (dbx)
For more information about stepping through your program, see Stepping Through a Program. For more information about the step and next commands, see step Command and next Command.
The call stack represents all currently active routines, which are those that have been called but have not yet returned to their respective caller. In the stack, the functions and their arguments are listed in the order in which they were called. A stack trace shows where in the program flow execution stopped and how execution reached this point. It provides the most concise description of your program’s state.
To display a stack trace, use the where command:
(dbx) stop in printf (dbx) run (dbx) where [1] printf(0x10938, 0x20a84, 0x0, 0x0, 0x0, 0x0), at 0xef763418 =>[2] printit(msg = 0x20a84 "hello world\n"), line 6 in "t.c" [3] main(argc = 1, argv = 0xefffe93c), line 13 in "t.c" (dbx)
For functions that were compiled with the -g option, the argument names and their types are known so accurate values are displayed. For functions without debugging information, hexadecimal numbers are displayed for the arguments. These numbers are not necessarily meaningful. For example, in the stack trace above, frame 1 shows the contents of the SPARC input registers $i0 through $i5.Only the contents of registers $i0 through $i1 are meaningful because only two arguments were passed to printf in the example shown in Stepping Through Your Program.
You can stop in a function that was not compiled with the -g option. When you stop in such a function, dbx searches down the stack for the first frame whose function is compiled with the -g option, in this case printit(), and sets the current scope to it. This is denoted by the arrow symbol (=>).
For more information about the call stack, see Efficiency Considerations. For more information about the current scope, see Program Scope.
Although a stack trace might contain enough information to fully represent the state of your program, you might need to see the values of more variables. The print command evaluates an expression and prints the value according to the type of the expression. The following example shows several simple C expressions:
(dbx) print msg msg = 0x20a84 "Hello world" (dbx) print msg[0] msg[0] = ’h’ (dbx) print *msg *msg = ’h’ (dbx) print &msg &msg = 0xefffe8b4
You can track when the values of variables and expressions change using data change breakpoints (see Setting Data Change Breakpoints (Watchpoints)). For example, to stop execution when the value of the variable count changes, type:
(dbx) stop change count
Runtime checking consists of two parts: memory access checking, and memory use and leak checking. Access checking checks for improper use of memory by the debugged application. Memory use and leak checking involves keeping track of all the outstanding heap space and then on demand or at termination of the program, scanning the available data spaces and identifying the space that has no references.
Memory access checking, and memory use and leak checking, are enabled with the check command. To enable memory access checking only:
(dbx) check -access
To enable memory use and memory leak checking:
(dbx) check -memuse
After enabling the types of runtime checking you want, run your program. The program runs normally but slowly because each memory access is checked for validity just before it occurs. If dbx detects invalid access, it displays the type and location of the error. You can then use dbx commands such as the where command to display the current stack trace or the print command to examine variables.
For more information about using runtime checking, see Using Runtime Checking.