|
| By Diane Meirowitz, Senior Staff Engineer, Fortran Compiler Team, December, 2006 |
|
| |
The Sun Studio Fortran compiler provides several command line options to enable run-time checks that can help you find bugs in your Fortran programs.
From the f95 man page:
-C
enables array bounds and array syntax conformance checking
-xcheck=[init_local | stkovf]
init_local initializes local and allocated variables to special
garbage values that are likely to to cause an arithmetic
exception if they are used before set
stkovf is a SPARC-only option that can detect stack overflow at run time.
-xassume_control=[check[,fatal]]
checks assertions specified with the ASSUME pragma, adding "fatal" causes
the warning to be an error
-xcommonchk
detects when a common block is defined THREADPRIVATE in some but not all
modules
-fpover
detects floating-point overflow in formatted input
The dbx rtc feature is not covered here, but can be extremely useful. It is currently available on SPARC platforms only. See the dbx manual for details.
The -C option enables, among other things, array bounds checking. If an array subscript is beyond the declared bounds of the array, an error message is printed and the program aborted.
Example:
%
cat test.f
subroutine copy(a,b)
integer a(:), b(:), i
do i = lbound(a,1), ubound(a,1)
a(i) = b(i)
end do
end subroutine
program
integer, parameter :: n = 20
integer a(1:n), b(1:n-1), i ! notice b is declared 1:n-1
interface
subroutine copy(a,b)
integer a(:), b(:), i
end subroutine
end interface
call copy(a,b)
end program
%
f95 -C test.f
%
a.out
****** FORTRAN RUN-TIME SYSTEM ******
Subscript out of range. Location: line 4 column 12 of 'x.f'
Subscript number 1 has value 20 in array 'B'
Abort
Optimization and -C:
The -C option can be used with any level of optimization. At higher optimization levels, checking usually has only minimal effect on performance, because the checks are optimized along with the rest of the code.
Arrays whose last dimension has size 1:
Some Fortran 77 programs declare dummy arguments with the last dimension of size 1, rather than *. In order to avoid run time errors in working programs, the compiler does not generate bounds checks for the last dimension for dummy or Cray pointee arrays whose last dimension has size 1.
The -C option also enables conformance checking of array syntax statements.
Example:
%
cat test.f
subroutine copy(a,b,n,m)
integer a(n), b(m)
a = b
end
program
integer, parameter :: n = 10
integer a(n), b(n-1)
call copy(a,b,n,n-1)
end
%
f95 -O3 -C test.f
%
a.out
****** FORTRAN RUN-TIME SYSTEM ******
An array expression does not conform : dim 1 is 9 , not 10
Location: line 4 column 11 of 'test.f'
Abort
The -xcheck=init_local option can help you detect when a local variable is used before set. When this option is used, local variables are initialized to unusual values that are likely to cause an exception when used. The initialization is currently done for:
Syntax on all SPARC platform releases and x86 platform releases after Sun Studio 11:
%
f95 -stackvar -xcheck=init_local file.f
Syntax on x86 platforms for Sun Studio 11 and earlier:
%
f95 -stackvar -qoption f95comp -xcheck=init_local file.f
Example:
%
cat test.f
subroutine init_local
real a, b, arr(10)
integer c, d
logical e
complex f
character*4 string
integer, pointer :: ptr(:)
integer v(10)
pointer(p,v)
print *, 'real=', a, ', int=', c
print *, 'logical=', e, ', complex=', f
print *, 'real array=', arr
print *, 'char*4=', string
allocate(ptr(6))
print *, 'allocated ptr=', ptr
p = malloc(sizeof(integer)*10)
print *, 'malloced cray ptr=', v
end subroutine
call init_local
end
%
f95 -stackvar -xcheck=init_local test.f
%
a.out
real= -NaN , int= -8388565
logical= T , complex= (-NaN,-NaN)
real array= -NaN -NaN -NaN -NaN -NaN -NaN -NaN -NaN -NaN -NaN
char*4=............
allocated ptr= -8388565 -8388565 -8388565 -8388565 -8388565 -8388565
malloced cray ptr= -8388565 -8388565 -8388565 -8388565 -8388565 -8388565
-8388565 -8388565 -8388565 -8388565
If, while debugging, you encounter a local variable with an unusual value such as the above, there is a good chance that the variable has not been initialized.
IMPORTANT NOTE: Do not rely on the particular initial values that the compiler currently uses, as they are subject to change.
The -xcheck=stkovf is currently available only on SPARC. It can be very useful for OpenMP programs, where the stack can be smaller than usual.
Example:
%
cat test.f
program
call overflow
end
subroutine overflow
integer, parameter :: n = 16000
integer*8 :: a(n), b(n), c(n), d(n)
a = b
c = d
print *,a(1:10),c(1:10)
end
%
f95 -stackvar -xcheck=stkovf test.f
%
limit stacksize 100 # to force a very small stack
%
a.out
Segmentation Fault
%
dbx a.out
dbx>
run
t@1 (l@1) signal SEGV (no mapping at the fault address) in __stack_grow_probing_impl at 0x1347c
0x0001347c: __stack_grow_probing_impl+0x0004: ldsb [%o0], %g0
The segmentation fault alerts you that stack overflow may have taken place. To check, run dbx; if the executable terminates in the above function, stack overlow has occurred.
The -xassume_control=check option causes the compiler to check the value of ASSUME pragmas, and generate a message when the value is not true. ASSUME pragmas are described in detail in the Fortran User's Guide. When they are not being used for run time checking, ASSUME pragmas can also improve optimization.
Example:
subroutine check (a,b,c)
integer a, b, c, d
c$pragma assume (a > 0, 1.0) ! 1.0 means 100% certainty, which enables checking
c$pragma assume (b > 0, 1.0)
print *, a, b, c
d = 0
c$pragma begin assume (__tripcount().lt.1000, 1.0)
do i = 1, c
d = d + 1
end do
c$pragma end assume
print *, d
end
call check(1, -1, 1000)
end
With -xassume_control=check when an assume error is detected a message is printed and execution continues:
%
f95 -xO3 -xassume_control=check test.f
%
a.out
Assume check failure at assume.f:5
Assume check failure at assume.f:10
1 -1 1000
1000
With -xassume_control=check,fatal when an assume error is detected a message is printed and the program is terminated:
%
f95 -xO3 -xassume_control=check,fatal test.f
%
a.out
Assume check failure at assume.f:5
NOTE: only ASSUME pragmas with probabilities of 1.0 are checked at run time, and any level of optimization may be used.
The -xcommonchk option adds run time checking to detect when a common block is defined THREADPRIVATE in some but not all program units. This option should be used for debugging only since it can degrade performance. The following is an example of its use.
common.f:
program
real a(100)
common /mycommon/ a
call abc()
end program
abc.f:
subroutine abc()
real a(100)
common /mycommon/ a
!$omp threadprivate (/mycommon/)
a = 0
end subroutine
%
f95 -O3 -xopenmp -xcommonchk common.f abc.f
%
setenv OMP_NUM_THREADS 2
%
a.out
ERROR (libmtsk): at abc.f:3. Inconsistent declaration of threadprivate
mycommon_ : Not declared as threadprivate at line 4 of common.f
The -fpover option enables a program to handle floating-point overflow in formatted input.
test.f:
integer status
real r
read (*, *, iostat=status) r
if (status.eq.1031) then
print *, 'Floating point overflow on input', r
end if
end
input:
1e+100
The -ftrap=%none flag is required with -fpover.
%
f95 -fpover -ftrap=%none test.f
%
a.out <input
Floating point overflow on input Inf
If the READ statement does not contain an IOSTAT= argument, a Fortran run time error is emitted when floating point overflow is detected in a formatted input value.
test.f:
integer status
real r
read (*, *) r
print *, r
end
%
f95 -fpover -ftrap=%none test.f
%
a.out <input
****** FORTRAN RUN-TIME SYSTEM ******
Error 1031: floating-point overflow on input
Unit: *
File: standard input
Abort
