11 Debugging DEC Fortran and DEC Fortran 90 Programs

11.1 Significant Supported Features

You can use Ladebug to debug Fortran programs on the Digital UNIX operating system. The following features are supported:

This chapter also discusses flags used with the Fortran compiler commands,+ Fortran data types in Ladebug, limitations on Ladebug support for Fortran, debugging a Fortran program that generates an exception, and locating unaligned data.


+ f77 is the DEC Fortran compile command, and f90 is the DEC Fortran 90 compile command. In this chapter, Fortran refers to both DEC Fortran and DEC Fortran 90.

11.2 Fortran Flags for Debugging

To prepare to use the Ladebug debugger on a Fortran program, invoke the compiler with the appropriate debugging flag: -g, -g2, or -g3 and, for DEC Fortran 90 only, - ladebug. For example, for DEC Fortran 90:

% f90 -g -ladebug -o squares squares.f90

For DEC Fortran:

% f77 -g -o squares squares.for

This f77 command compiles and links the program squares.for without optimization but with symbol table information needed for symbolic debugging with Ladebug. The executable file is named squares instead of a.out.

The -gn flags control the amount of information placed in the object file for debugging.

For Digital UNIX Version 3.2 systems, Table 11-1 summarizes the information provided by the debugger-related flags and their relationship to the -On flags, which control optimization. Refer to your language compiler documentation for the latest information on compiler flags used on Digital UNIX Version 4.0 systems.


Note
Ladebug cannot distinguish between a Fortran-77 and a Fortran-90 compilation unit because the respective compilers do not make such distinctions. The value of $lang is always "Fortran" in both cases.

Table 11-1 Summary of Symbol Table Flags

Flag  Traceback Information  Debugging Symbol Table Information  Effect on -On Flags 
-g0   No  No  Default is - O4 (full optimization). 
-g1 (default)  Yes  No  Default is -O4 (full optimization). 
-g2 or - g   Yes  Yes. For unoptimized code only.  Changes default to -O0 (no optimization). 
-g3   Yes  Yes  Default is -O4
-ladebug (f90 only)   Yes  Describes Fortran-90 arrays in a manner that Ladebug understands.  No effect. 

Traceback information and symbol table information are both necessary for debugging. They enable the debugger to:

Typical uses of the debugging flags at the various stages of program development are as follows:

Traceback and symbol table information result in a larger object file. When you have finished debugging your program, you can remove traceback information with the the strip command (see strip(1) ). To remove symbol table information, you can compile and link again with -g0 or -g1 to create a new executable program.

If your program generates an exception, recompile using the - fpen flag (see Section 11.7).

For more information on program development and run-time environments, see the DEC Fortran or DEC Fortran 90 user manual.


+ -g1 results in a larger object file than -g0 but smaller than the other gn flags

11.3 Displaying Fortran Variables

When the $lang debugger variable is set to Fortran, command names and program identifiers are case insensitive. For more information about the $lang debugger variable, see Section 11.6.

To refer to a variable named J, use either the uppercase letter J or its lowercase equivalent, j.

You can also enter Ladebug command names in uppercase or lowercase. For example, the following two commands are equivalent:

(ladebug) PRINT J
(ladebug) print j

11.3.1 Fortran Common Block Variables

You can display the values of variables in a Fortran common block using Ladebug commands such as print or whatis.

To display the entire common block, use the common block name. For example:

(ladebug) list 1,11
      1       PROGRAM EXAMPLE
      2
      3       INTEGER*4 INT4
      4       CHARACTER*1 CHR
      5       COMMON /COM_STRA/ INT4, CHR
      6
      7       CHR = 'L'
      8
>     9       PRINT *, INT4, CHR
     10
     11       END
(ladebug) print com_stra
COMMON
    INT4 = 0
    CHR = "L"

To display a specific variable in the common block, use only the field name. For example:

(ladebug) PRINT CHR
"L"

If your program contains a common block and a member of the same name, the common block will be occluded by the member.

11.3.2 Fortran Derived-Type Variables

Variables in a Fortran 90 derived-type (TYPE statement) are represented in Ladebug commands, such as print or whatis , using Fortran 90 syntax form.

For derived-type structures, use:

For example:

(ladebug) list 3,11
      3       TYPE X
      4       INTEGER A(5)
      5       END TYPE X
      6
      7       TYPE(X) Z
      8
      9       Z%A = 1
     10
>    11       PRINT*, Z%A
(ladebug) print Z%A
(1) 1
(2) 1
(3) 1
(4) 1
(5) 1

11.3.3 Fortran Record Variables

Variables in a Fortran record structure (STRUCTURE statement) are represented in a fashion similar to derived-type.

For record structures, use:

For example:

(ladebug) l 3,13
      3       STRUCTURE /STRA/
      4          INTEGER*4 INT4
      5          CHARACTER*1 CHR
      6       END STRUCTURE
      7
      8       RECORD /STRA/ REC
      9
     10       REC.CHR = 'L'
     11       REC.INT4 = 6
     12
>    13       PRINT *, REC.CHR, REC.INT4
(ladebug) print rec%int4
6
(ladebug) print rec.int4
6

To view all fields in the record structure, type the name of the record structure, such as rec (instead of rec%int4 or rec.int4 in the previous example).

11.3.4 Fortran Array Variables

For array variables, put subscripts within parentheses, as with Fortran source statements. For example:

(ladebug) assign arrayc(1)=1

You can print out all elements of an array using its name. For example:

(ladebug) print arrayc

(1) 1
(2) 0
(3) 0

Avoid displaying all elements of a large array. Instead, display specific array elements or array sections. For example, to print array element arrayc(2):

(ladebug) print arrayc(2)

(2) 0

11.3.4.1 Array Sections

Fortran provides an array notation known as an array section. Array sections consist of a three parts, a starting element, an ending element, and a stride. For more information on arrays, see the DEC Fortran or DEC Fortran 90 user manual.

Consider the following array declarations:

INTEGER, DIMENSION(0:99)    :: arr
INTEGER, DIMENSION(0:9,0:9)  :: TenByTen

Assume that each array has been initialized to have the value of the index in each position, for example, TenByTen(5,5) = 55, arr(43) = 43. The following expressions will be accepted by the debugger:

(ladebug) print arr(2)

2
(ladebug) print arr(0:9:2) 

(0) = 0
(2) = 2
(4) = 4
(6) = 6
(8) = 8
(ladebug) print TenByTen(:,3)

(0,3) = 3
(1,3) = 13
(2,3) = 23
(3,3) = 33
(4,3) = 43
(5,3) = 53
(6,3) = 63
(7,3) = 73
(8,3) = 83
(9,3) = 93

The only operations permissible on array sections are whatis and print .

Ladebug supports the array section notation for both Fortran-90 and Fortran-77 programs.

11.3.4.2 Assignment to Arrays

Ladebug does not support assignments to whole arrays, only single array elements.

11.3.5 DEC Fortran 90 Module Variables

To refer to a variable defined in a module, insert a dollar sign ($), the module name, and another dollar sign ($) before the variable name. For example, with a variable named J defined in a module named modfile (statement MODULE MODFILE), enter the following command to display its value:

(ladebug) list 5,7
        5     USE MODFILE
        6     INTEGER*4 J
        7     CHARACTER*1 CHR

11.3.6 DEC Fortran 90 Pointer Variables

DEC Fortran 90 supports two types of pointers:

The following example shows Fortran 90 pointers displayed in their corresponding source form with a whatis command. In the following example, the -ladebug switch is used to allow display of pointers to arrays. Only the display of pointers is currently supported; it is not currently possible to change the location to which the pointer points:

% f90 -g -ladebug ptr.f90
% ladebug ./a.out
Welcome to the Ladebug Debugger Version x.y-zz
------------------
object file name: ./a.out
Reading symbolic information ...done
(ladebug)stop in ptr
[#1: stop in ptr ]
(ladebug) list 1:13
      1       program ptr
      2
      3       integer, target :: x(3)
      4       integer, pointer :: xp(:)
      5
      6       x = (/ 1, 2, 3/)
      7       xp => x
      8
      9       print *, "x = ", x
     10       print *, "xp = ", xp
     11
     12       end
(ladebug) run
[1] stopped at [ptr:6 0x120001838]
      6       x = (/ 1, 2, 3/)
(ladebug) whatis x
integer*4 x (1:3)

Since xp has not been assigned to point to anything yet, it is still a generic pointer:

(ladebug) whatis xp
integer*4 (:) xp
(ladebug) S
stopped at [ptr:7 0x120001880]
      7       xp => x
(ladebug)
stopped at [ptr:9 0x120001954]
      9       print *, "x = ", x
(ladebug)
 x =            1           2           3
stopped at [ptr:10 0x1200019c8]
     10       print *, "xp = ", xp
(ladebug)
 xp =            1           2           3
stopped at [ptr:12 0x120001ad8]
     12       end

Now that xp points to x, it takes on the size, shape and values of x:

(ladebug) whatis xp
integer*4 xp (1:3)
(ladebug) print xp
(1) 1
(2) 2
(3) 3

(ladebug) quit
%

The following example shows DEC Fortran CRAY-style pointers displayed in their corresponding source form with a whatis command:

% f90 -g -ladebug cray.f90
% ladebug ./a.out
Welcome to the Ladebug Debugger Version x.y-zz
------------------
object file name: ./a.out
Reading symbolic information ...done
(ladebug) stop at 14
[#1: stop at "cray.f90":14 ]
(ladebug) run
[1] stopped at [cray:14 0x1200017e4]
     14       end
(ladebug) whatis p
real*4 (1:10) pointer p
(ladebug) print p
0x140002c00 = (1) 10
(2) 20
(3) 30
(4) 40
(5) 50
(6) 60
(7) 70
(8) 80
(9) 90
(10) 100

(ladebug) l 1:14
      1       program cray
      2
      3       real i(10)
      4       pointer (p,i)
      5
      6       n = 5
      7
      8       p = malloc(sizeof(i(1))*n)
      9
     10       do j = 1,10
     11          i(j) = 10*j
     12       end do
     13
>    14       end
(ladebug) quit

11.3.7 Complex Variable Support

Ladebug supports COMPLEX, COMPLEX*8, and COMPLEX*16 variables and constants in expressions.

Consider the following Fortran program:

 PROGRAM complextest
    COMPLEX*8 C8 /(2.0,8.0)/
    COMPLEX*16 C16 /(1.23,-4.56)/
    REAL*4     R4 /2.0/
    REAL*8     R8 /2.0/
    REAL*16    R16 /2.0/
    integer*2  i2 /2/
    integer*4  i4 /2/
    integer*8  i8 /2/

    TYPE *, "C8=", C8
    TYPE *, "C16=", C16

    end

Ladebug supports basic arithmetic operators, display and assignment on variables and constants of the COMPLEX type. For example:

Welcome to the Ladebug Debugger Version x.y-zz
------------------
object file name: complex
Reading symbolic information ...done
(ladebug) stop in complextest
[#1: stop in complextest ]
(ladebug) run
[1] stopped at [complextest:15 0x1200017b4]
     15       TYPE *, "C8=", C8
(ladebug) whatis c8
complex c8
(ladebug) whatis c16
double complex c16
(ladebug) print c8
(2, 8)
(ladebug) print c16
(1.23, -4.56)
(ladebug) whatis (-5,6.78E+12)
double complex
(ladebug) print (c8*c16)/(c16*c8)
(1, 0)
(ladebug) a c16=(-2.3E+10,4.5e-2)
(ladebug) print c16
(-23000000512, 0.04500000178813934)
(ladebug)

11.4 Limitations on Ladebug Support for Fortran

Ladebug and the Digital UNIX operating system support the Fortran language with certain limitations, that are described in the following sections.

Be aware of the following data-type limitations when you debug a Fortran program:

The following limitations apply only to DEC Fortran 90:

11.5 Use of Alternate Entry Points

If a subprogram uses alternate entry points (ENTRY statement within the subprogram), Ladebug handles alternate entry points as a separate subprogram, including:

For example, the following is a fragment of a Fortran program and a debugging session:

      program aep

      call foo(1,2,3,4)
      call bar(4,5,6)
      end

      subroutine foo(I,J,K,I1)
      INTEGER*4 I,J,K,L,I1

      write (6,*) 'Entered via foo: ', i, j, k, I1
      write (6,*) '*****************************'
      goto 1000

      entry bar(J,K,L)

      write (6,*) 'Entered via bar: ', j, k, l
      write (6,*) '*****************************'

      1000 write (6,*) 'Exiting foo & bar'
      return
      end

Welcome to the Ladebug Debugger Version x.y-zz
------------------
object file name: aep
Reading symbolic information ...done
(ladebug) stop in foo
[#1: stop in foo ]
(ladebug) stop in bar
[#2: stop in bar ]
(ladebug) status
#1 PC==0x120001868 in foo "aep.f":10 { break }
#2 PC==0x1200019ac in bar "aep.f":16 { break }
(ladebug) run
[1] stopped at [foo:10 0x120001868]
     10       write (6,*) 'Entered via foo: ', i, j, k, I1
(ladebug) where
>0  0x120001868 in foo(I=1, J=2, K=3, I1=4) aep.f:10
#1  0x120001814 in aep() aep.f:3
#2  0x1200017b0 in main() for_main.c:203
(ladebug) c
Entered via foo:            1           2           3           4
*****************************
Exiting foo & bar
[2] stopped at [bar:16 0x1200019ac]
     16       write (6,*) 'Entered via bar: ', j, k, l
(ladebug) where
>0  0x1200019ac in bar(J=4, K=5, L=6) aep.f:16
#1  0x12000182c in aep() aep.f:4
#2  0x1200017b0 in main() for_main.c:203
(ladebug) c
Entered via bar:            4           5           6
*****************************
Exiting foo & bar
Thread has finished executing
(ladebug) quit

11.6 Debugging Mixed-Language Programs

The Ladebug debugger lets you debug mixed-language programs. Program flow of control across subprograms written in different languages is transparent.

The debugger automatically identifies the language of the current subprogram or code segment on the basis of information embedded in the executable file. For example, if program execution is suspended in a subprogram in Fortran, the current language is Fortran. If the debugger stops the program in a C function, the current language becomes C. The current language determines for the debugger the valid expression syntax and the semantics used to evaluate an expression.

The debugger sets the $lang variable to the language of the current subprogram or code segment. By manually setting the $lang debugger variable, you can force the debugger to interpret expressions used in commands by the rules and semantics of a particular language. For example, you can check the current setting of $lang and change it as follows:

(ladebug) print $lang
"C++"
(ladebug) set $lang = "Fortran"

When the debugger reaches the end of your program, the $lang variable is set to the language of the main program.

11.7 Debugging a Program That Generates an Exception

If your program encounters an exception at run time, to make it easier to debug the program, recompile and relink with the following f90 flags or f77 flags before debugging the cause of the exception:

Use the Ladebug commands catch and ignore to control whether Ladebug displays and handles exceptions (catches them), or ignores exceptions so that they are handled by the Fortran run-time library.

To obtain the appropriate Fortran run-time error message when debugging a program that generates an exception, you may need to use the appropriate ignore command before running the program. For instance, use the following command to tell Ladebug to ignore floating-point exceptions and pass them through to the Fortran run-time library:

(ladebug) ignore fpe

Because the where command works only if the debugger is catching the signal, the ignore command prevents the where command from working. You may want to use the where command when an exception occurs to locate the part of the program causing the error. You need to consider this factor when you use the ignore command.

11.8 Debugging Optimized Programs

The Fortran compiler performs code optimizations (-O4 ) by default unless you specify -g2 (or - g ) . See the DEC Fortran or DEC Fortran 90 user manual for a discussion of compiler optimizations.

Debugging optimized code is recommended only under special circumstances (such as a problem that shows up in an optimized program may disappear when you specify the -O0 flag). Before you attempt to debug optimized code, read Section 11.2.

One aid to debugging optimized code is the -show code flag. This flag generates a listing file that shows the compiled code produced for your program. By referring to a listing of the generated code, you can see exactly how the compiler optimizations affected your code. This lets you determine the debugging commands you need in order to isolate the problem.

Another aid is a set of messages displayed by Ladebug when you try to perform a Ladebug operation on a language construct that has been optimized. For example, if the Fortran compiler can determine that an entire Fortran 90 statement is not needed for correct operation of the program (such as an unnecessary CONTINUE statement), that statement is not represented in the object code. As a result, Ladebug will use the next available line.

For more information on optimizations, see the DEC Fortran or DEC Fortran 90 user manual.