ФОРТРАН: в подпрограммах происходит сбой проверки за пределами?

У меня есть довольно простой фрагмент кода (урезанный до сути из более крупной программы).

Я передаю массив и размер массива подпрограмме. Я не получаю ошибки, если переданный размер не соответствует фактическому размеру массива. И я даже могу манипулировать несуществующими частями массива!!! (Я перезаписываю память, которую не должен перезаписывать).

Вот подпрограмма:

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

а вот основная программа

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

Если я скомпилирую с ifort и -check all, он поймает ошибку только в основной программе, но не в подпрограмме.

Есть ли способ поймать ошибку в подпрограмме?


person smoebius    schedule 06.01.2014    source источник
comment
Это не ошибка, а особенность FORTRAN. В любом случае, я согласен с тем, что более современные компиляторы должны иметь возможность проверить это, и здесь Intel не выдает предупреждения.   -  person John Alexiou    schedule 06.01.2014


Ответы (1)


Да. Объявить массив как dimension(:) в подпрограмме -- массив предполагаемой формы. Использование этого объявления Fortran >90 требует, чтобы интерфейс процедуры был известен вызывающей стороне — самый простой способ — иметь процедуру в модуле и use этот модуль в вызывающей стороне. На самом деле вам не нужно передавать размер массива подпрограмме — вы можете определить его как size(arr). Я оставил аргумент narr, чтобы сохранить ошибку.

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
person M. S. B.    schedule 06.01.2014
comment
Спасибо за ответ. Исходная подпрограмма находится в модуле, так что здесь нет проблем, но я умышленно не хотел использовать в подпрограммах массивы предполагаемого размера. Я надеялся, что компилятор скажет мне, что я передаю массив неправильного размера. Есть ли способ получить эту функцию или мне придется вручную проверять size(arr) == narr? - person smoebius; 07.01.2014
comment
Если вы скажете компилятору, что массив имеет размер narr, он поверит вам на слово, правы вы или нет. Меньше работы и меньше ошибок при использовании массива предполагаемого размера, а не в явной передаче аргумента для размера. Я рекомендую использовать метод Fortran ›=90 и использовать массивы предполагаемого размера и встроенные функции, такие как size. - person M. S. B.; 07.01.2014