DIGITAL Fortran 90
User Manual for
DIGITAL UNIX Systems


Previous Contents Index

4.4 Sample Program and Debugging Session

Example 4-1 shows a program called SQUARES that requires debugging. The program was compiled and linked without diagnostic messages from either the compiler or the linker. However, this program contains a logic error in an arithmetic expression.

Compiler-assigned line numbers have been added in the example so that you can identify the source lines referenced in the explanatory text.

Example 4-1 Sample Program SQUARES

     1        PROGRAM SQUARES 
     2        INTEGER INARR(20), OUTARR(20) 
     3  C  ! Read the input array from the data file. 
     4        OPEN(UNIT=8, FILE='datafile.dat', STATUS='OLD') 
     5        READ(8,*,END=5) N, (INARR(I), I=1,N) 
     6     5  CLOSE (UNIT=8) 
     7  C ! Square all nonzero elements and store in OUTARR. 
     8        K = 0 
     9        DO I = 1, N 
     10         IF (INARR(I) .NE. 0) THEN 
     11            OUTARR(K) = INARR(I)**2 
     12         ENDIF 
     13       END DO 
     14 
     15 C ! Print the squared output values.  Then stop. 
     16       PRINT 20, K 
     17   20  FORMAT (' Number of nonzero elements is',I4) 
     18       DO I = 1, K 
     19         PRINT 30, I, OUTARR(I) 
     20   30    FORMAT(' Element',I4,' has value',I6) 
     21       END DO 
     22      END PROGRAM SQUARES 

The program SQUARES performs the following functions:

  1. Reads a sequence of integer numbers from a data file and saves these numbers in the array INARR (lines 4 and 5). The file datafile.dat contains one record with the integer values 4, 3, 2, 5, and 2. The first number (4) indicates the number of data items that follow.
  2. Enters a loop in which it copies the square of each nonzero integer into another array OUTARR (lines 8 through 13).
  3. Prints the number of nonzero elements in the original sequence and the square of each such element (lines 16 through 21).

When you run SQUARES, it produces the following output, regardless of the number of nonzero elements in the data file:


% squares
Number of nonzero elements is   0

The error occurs because variable K, which keeps track of the current index into OUTARR, is not incremented in the loop on lines 9 through 13. The statement K = K + 1 should be inserted just before line 11.

Example 4-2 shows how to start the debugging session and how to use the character-cell interface to the Ladebug debugger to find the error in the sample program in Example 4-1. Comments keyed to the callouts follow the example.

Example 4-2 Sample Debugging Session Using Program Squares

 
% f90 -g -ladebug -o squares squares.f90  (1)
% ladebug squares                         (2)
Welcome to the Ladebug Debugger Version x.x-xx 
--------------- 
object file name: squares 
reading symbolic information ... done
(ladebug) list 1,9                        (3) 
      1   PROGRAM SQUARES 
      2     INTEGER INARR(20), OUTARR(20) 
      3 C  ! Read the input array from the data file. 
>     4      OPEN(UNIT=8, FILE='datafile.dat', STATUS='OLD') 
      5      READ(8,*,END=5) N, (INARR(I), I=1,N) 
      6    5 CLOSE (UNIT=8) 
      7 C  ! Square all nonzero elements and store in OUTARR. 
      8      K = 0 
      9      DO 10 I = 1, N
(ladebug) stop at 8                       (4)
[#1: stop at "squares.f90":8]
(ladebug) run                             (5)
[1] stopped at ["squares.f90":4 0x120001a88] 
>   8      K = 0
(ladebug) step                            (6) 
stopped at [squares:9 0x120001a90] 
      9        DO 10 I = 1, N
(ladebug) print n, k                      (7)
4 0  
(ladebug) step                            (8)
stopped at [squares:10 0x120001ab0]] 
     10       IF(INARR(I) .NE. 0)  THEN
(ladebug) s
stopped at [squares:11 0x1200011acc] 
     11       OUTARR(K) =   INARR(I)**2
(ladebug) print i, k                      (9)
1 0
(ladebug) assign k = 1                    (10)
(ladebug) stop k in squares               (11)
[#2: stop if K changes in subroutine squares() ]
(ladebug) cont                            (12)
Number of nonzero elements is   1
Element   1 has value     4
Process has exited with status 0
(ladebug) quit                            (13)
% vi squares.f90                          (14)
   .
   .
   .
10:       IF(INARR(I) .NE. 0) THEN
11:           K = K + 1
12:           OUTARR(K) = INARR(I)**2
13:       ENDIF
   .
   .
   .
% f90 -g -ladebug -o squares squares.f90     (15)
% ladebug squares                         
Welcome to the Ladebug Debugger Version x.x-xx 
Reading symbolic information ...done
(ladebug) when at 12 {print k}               (16)
[#1: when at "squares.for":12 { print K} ]
(ladebug) run                                (17)
[1] when [squares:12 0x120001ae0] 
1
[1] when [squares:12 0x120001ae0] 
2
[1] when [squares:12 0x120001ae0] 
3
[1] when [squares:12 0x120001ae0] 
4
Number of nonzero elements is   4
Element   1 has value     9
Element   2 has value     4
Element   3 has value    25
Element   4 has value     4
Process has exited with status 0
(ladebug) quit                           
% 

  1. On the f90 command line, the -g and -ladebug options direct the compiler to write the symbol information associated with SQUARES into the object file for the debugger. It also disables most optimizations done by the compiler to ensure that the executable code matches the source code of the program.
  2. The shell command ladebug squares runs the debugger, which displays its banner and the debugger prompt, (ladebug) . This command specifies the executable program as a file named squares . You can now enter debugger commands.
    After the ladebug squares command, execution is initially paused before the start of the main program unit (before program SQUARES, in this example).
    To use the dbx debugger, type the following shell command instead of ladebug squares :


    % dbx squares                               
    dbx version x.x 
    Type 'help' for help. 
    squares:   4  OPEN(UNIT=8, FILE='datafile.dat', STATUS='OLD') 
    (dbx) 
    

  3. The list 1,9 command prints lines 1 through 9.
  4. The command stop at 8 sets a breakpoint (1) at line 8.
  5. The run command begins program execution. The program stops at the first breakpoint, line 8, allowing you to examine variables N and K before program completion.
  6. The step advances the program to line 9.
    The step command ignores source lines that do not result in executable code; also, by default, the debugger identifies the source line at which execution is paused.
    To avoid stepping into a subprogram, use the next command instead of step
  7. The command print n, k displays the current values of variables N and K. Their values are correct at this point in the execution of the program.
  8. The two step commands continue executing the program into the loop (lines 9 to 11) that copies and squares all nonzero elements of INARR into OUTARR.
    Certain commands can be abbreviated. In this example, the s command is an abbreviation of the step command.
  9. The command print i, k displays the current values of variables I and K.
    Variable I has the expected value, 1. But variable K has the value 0 instead of the expected value, 1. To fix this error, K should be incremented in the loop just before it is used in line 11.
  10. The assign command assigns K the value 1.
  11. The stop k in squares command sets a breakpoint that is triggered every time the value of variable K changes when in the routine (or program) named squares. In the original version of the program, this breakpoint is never executed, indicating that the value of variable K never changes (a programming error).
  12. To test the patch, the cont command (abbreviation for continue ) resumes execution from the current location.
    The program output shows that the patched program works properly, but only for the first array element. Because the breakpoint ( stop k in squares command) does not occur, the value of K did not change and there is a problem. The Ladebug message "Process has exited with status 0" shows that the program executed to completion.
    When using the dbx debugger, the message "Program terminated normally" shows that the program executed to completion.
  13. The quit command returns control to the shell so that you can correct the source file and recompile and relink the program.
  14. The shell command vi runs a text editor and the source file is edited to add K = K + 1 after line 10, as shown. (Compiler-assigned line numbers have been added to clarify the example.)
  15. The revised program is compiled and linked.
    The shell command ladebug squares (or dbx squares ) starts the debugger, using the revised program so that its correct execution can be verified.
  16. The when at 12 {print k} command reports the value of K at each iteration through the loop.
  17. The run command starts execution.
    The displayed values of K confirm that the program is running correctly.
    The quit command ends the debugging session, returning control to the shell.

4.5 Summary of Debugger Commands

Table 4-2 lists the more frequently used debugging commands available in Ladebug and dbx. Many of these commands can be abbreviated (such as typing c instead of continue ). When using the debugger with a windowing interface, you can access these commands by using the windowing interface (command buttons and command menu). For a complete list of available debugger commands, see the ladebug(1) reference page.

Table 4-2 Summary of Debugger Commands
Command Example Description
catch Displays all signals that the debugger is currently set to catch (see also ignore ).
catch fpe Tells the debugger to catch the fpe signal (or the signal specified). This prevents the specified signal from reaching the DIGITAL Fortran 90 RTL. The signals that the DIGITAL Fortran 90 RTL arranges to catch are listed in Section 8.3.
catch unaligned Tells the debugger to catch the unaligned signal, as further described in Section 4.10. The signals that the DIGITAL Fortran 90 RTL arranges to catch are listed in Section 8.3.
continue Resumes running the program that is being debugged.
delete 2 Removes the breakpoint or tracepoint identified by event number 2 (see also status ).
delete all Removes all breakpoints and tracepoints.
help Displays debugger help text using the more command.
history 5 Displays the last 5 debugger commands.
ignore Displays the signals the debugger is currently set to ignore. The ignored signals are allowed to pass directly to the DIGITAL Fortran 90 RTL. (see also catch ).
ignore fpe Tells the debugger to ignore the fpe signal (or the signal specified). This allows the specified signal to pass directly to the DIGITAL Fortran 90 RTL, allowing message display. The signals that the DIGITAL Fortran 90 RTL arranges to catch are listed in Section 8.3.
ignore unaligned Tells the debugger to ignore the unaligned signal (the default).
kill Terminates the program process, leaving the debugger running and its breakpoints and tracepoints intact for when the program is rerun.
list Displays source program lines. To list a range of lines, add the starting line number, a comma (,), and the ending line number, such as list 1,9 .
print k Displays the value of the specified variable, such as K.
printregs Displays all registers and their contents.
next Steps one source statement but does not step into calls to subprograms (compare with step ).
quit Ends the debugging session.
run Runs the program being debugged. You can specify program arguments and redirection.
rerun Runs the program being debugged again. You can specify program arguments and redirection.
return routine-name When using the step command, if you step into a subprogram that does not require further investigation, use the return command to return to the point of the subprogram call and then use a next or run command to step over the subprogram call.

The routine-name is the name of the routine, usually named by a PROGRAM, SUBROUTINE, or FUNCTION statement. If there is no PROGRAM statement, the debugger refers to the main program with a prefix of main$ followed by the file name.

sh more progout.f90 Executes the shell command more to display file progout.f90 , then returns to the debugger environment.
show thread Lists all threads known to the Ladebug debugger.
status Displays breakpoints and tracepoints with their event numbers (see also delete ).
step Steps one source statement, including stepping into calls of a subprogram. For DIGITAL Fortran 90 I/O statements, intrinsic procedures, 3f library routines, or other subprograms, use the next command instead of step to step over the subprogram call. Compare with next ; also see return .
stop k in foo Stops execution (breakpoint) if the value of variable K changes in routine foo and displays a message.
stop in foo Stops execution (breakpoint) at the beginning of routine foo.
stop at 100 Stops execution at line 100 (breakpoint) of the current source file.
stopi at xxxxxxxxx Stops execution at address xxxxxxx of the current source file.
thread [ n] Identifies or sets the current thread context (ladebug).
trace i Displays a message when the value of variable I changes (tracepoint). Alternatively, use the when at or when in commands.
watch location Displays a message when the debugger accesses the specified memory location. For example, watch 0x140000170 .
watch variable m Displays a message when the debugger accesses the variable specified by m.
whatis sum Displays data type of specified symbol.
when at 9 { command} When a specified line (such as 9) is reached, the command or commands are executed. For example, when at 9 {print k} prints the value of variable K when the program executes source code line 9.
when in name { command} When a procedure specified by name is reached, the command or commands are executed. For example, when in calc_ave {print k} prints the value of variable K when the program begins executing the procedure named calc_ave.
where Displays the call stack.
where thread all Displays the stack traces of all threads.

The debuggers support other special-purpose commands. For example:

For More Information:


Previous Next Contents Index