I have found a bug in a large program where a subroutine was written as:
program main
implicit none
real, dimension(6) :: x
call f(x, 7)
write (*,*) x
contains
subroutine f(x, n)
integer :: n
real, dimension(n) :: x
integer :: i
do i = 1, n
x(i) = 0.0
end do
end subroutine f
end program main
This program runs fine with both ifort and gfortran and bounds checking even though the code is obviously buggy. Is there an option to catch those kind of bugs?
PS: Here are the two commands that generate binaries that run fine
ifort -check all main.f90 -o main
gfortran -fbounds-check main.f90 -o main
The cout statement inside main prints 40, and cout in findSize prints 8. The reason is, arrays are always passed pointers in functions, i.e., findSize(int arr[]) and findSize(int *arr) mean exactly same thing. Therefore the cout statement inside findSize() prints the size of a pointer.
To determine the size of your array in bytes, you can use the sizeof operator: int a[17]; size_t n = sizeof(a); On my computer, ints are 4 bytes long, so n is 68. To determine the number of elements in the array, we can divide the total size of the array by the size of the array element.
Can the sizeof operator be used to tell the size of an array passed to a function? No. There�s no way to tell, at runtime, how many elements are in an array parameter just by looking at the array parameter itself. Remember, passing an array to a function is exactly the same as passing a pointer to the first element.
Disclaimer: The author ask for an option to catch the bug. This answer doesn't provide it.
If the array is an assumed shaped (dimension(:)
), the check is performed:
ifort 15.5
forrtl: severe (408): fort: (2): Subscript #1 of the array X has value 7 which is greater than the upper bound of 6
gfortran 6.1.0
Fortran runtime error: Index '7' of dimension 1 of array 'x' above upper bound of 6
whereas when its and assumed size (dimension(*)
) or explicited shape (dimension(n)
) it is not. It may be purposely designed.
ifort manual
Array bounds checking is not performed for arrays that are dummy arguments in which the last dimension bound is specified as * or when both upper and lower dimensions are 1.
gfortran manual dosn't detail that point
This is an important class of programming error where compilers are not too great when it comes to detecting instances. As the question notes, both the Intel and GNU compilers fail to detect a problem when compiling with array access bounds checking.
Indeed, I am not aware of other flags which turn on such checking in the compiler at run-time.
However, in some cases both gfortran and ifort can catch the error. When the actual or argument has an explicit size given by a constant expression and the interface of the subroutine is "known" (not necessarily explicit) the error may be detected. With gfortran, the procedure being in the same file may enable this checking and with ifort the option -warn interfaces
(maybe after -gen_interfaces
) does the same.
Now, this as this is an important class of error we can go beyond the simple limits of the question. As the answer by PTRK says, the error can be mitigated by not using explicit shape dummies.
Additionally, the NAG compiler, as one example, does offer such run-time checks for actual arguments being no shorter than associated dummy arguments. Compiled with -C
the code of the question gives the run-time error:
line 8: Invalid reference to procedure MAIN:F - Dummy array X (number 1) has 7 elements but actual argument only has 6 elements
Program terminated by fatal error
It is always worth considering a variety of tools to catch different aspects of potential programming errors or unwise practices.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With