Search code examples
arraysfortransubroutineintel-fortran

FORTRAN: out of bounds check fails in subroutines?


I have a rather simple piece of code (reduced to the essentials from bigger program).

I pass an array and the size of the array to a subroutine. I get no error if the passed size does not match the actual size of the array. And I can even manipulate the parts of the array that don't "exist" !!! (I overwrite memory that I shouldn't overwrite).

Here is the subroutine:

subroutine sub(arr, narr)
implicit none
integer, intent(in) :: narr
double precision, dimension(narr) :: arr
integer :: j

do j = 1, narr
  ! print all the values
  write(*, '("Arr[",I0,"] = ",f0.10)') j, arr(j)
  ! change the values
  arr(j) = -10d0
enddo

end subroutine

and here the main program

program main

implicit none

integer, parameter :: narr = 5
! the array is made smaller
double precision, dimension(narr - 2) :: array

integer :: j

! assign values to array
array = (/ (1d0*j,   j = 1,narr - 2) /)

! print using the subroutine
print*, "inside subroutine" 
call sub(array, narr)

! print outside the subroutine
print *, " "
print *, "outside subroutine"
do j = 1, narr
  write(*, '("Arr[",I0,"] = ",f0.10)') j, array(j)
enddo

end program

If I compile with ifort and "-check all" it only catches the error in the main program, but not in the subroutine.

Is there a way to catch also the error in the subroutine ?


Solution

  • Yes. Declare array as dimension(:) in the subroutine -- assumed-shape array. Using this Fortran >90 declaration requires that the procedure interface be known to the caller -- the easiest way is to have the procedure in a module and use that module in the caller. You don't actually need to pass the size of the array to the subroutine -- you can determine it as size(arr). I have left the argument narr to retain the bug.

    module MySub
    
    contains
    
    subroutine sub(arr, narr)
    implicit none
    integer, intent(in) :: narr
    double precision, dimension(:) :: arr
    integer :: j
    
    do j = 1, narr
      ! print all the values
      write(*, '("Arr[",I0,"] = ",f0.10)') j, arr(j)
      ! change the values
      arr(j) = -10d0
    enddo
    
    end subroutine
    
    end module MySub
    
    
    program main
    
    use MySub
    
    implicit none
    
    integer, parameter :: narr = 5
    ! the array is made smaller
    double precision, dimension(narr - 2) :: array
    
    integer :: j
    
    ! assign values to array
    array = (/ (1d0*j,   j = 1,narr - 2) /)
    
    ! print using the subroutine
    print*, "inside subroutine"
    call sub(array,narr)
    
    ! print outside the subroutine
    print *, " "
    print *, "outside subroutine"
    do j = 1, narr
      write(*, '("Arr[",I0,"] = ",f0.10)') j, array(j)
    enddo
    
    end program