4

The following code, combining module procedures and external procedures:

module module_dummy

  implicit none

contains

  subroutine foo(a)

    real, intent(inout) :: a(:)

    call bar(a)

  end subroutine foo

end module module_dummy

program main

  use module_dummy

  implicit none 

  integer, parameter :: nelems = 100000000
  real,  allocatable :: a(:)

  allocate( a(nelems) )
  a = 0.0
  call foo(a)
  print *, a(1:10)
  deallocate(a)

end program main

subroutine bar(a)

  implicit none

  real, intent(inout) :: a(:)

  a = 1.0      

end subroutine bar

seems to fail either:

  1. with a segmentation fault
  2. printing a block of 0.000 instead of a block of 1.000

on any platform I have tried so far. The problem is related to the implicit interface declaration of bar, and in fact the issue can be solved adding in any way an explicit interface, e.g. using:

module module_dummy

  implicit none

contains

  subroutine foo(a)

    interface 
       subroutine bar(x)
         real, intent(inout) :: x(:)
       end subroutine bar
    end interface

    real, intent(inout) :: a(:)

    call bar(a)

  end subroutine foo

end module module_dummy

or declaring bar inside a module to be used by module_dummy.

Anyhow I really don't understand what is the error in the first place. What I have found on the Fortran 90 standard (sec. 12.3.2.4) says that:

The type, type parameters, and shape of dummy arguments of a procedure referenced from a scoping unit where the interface of the procedure is implicit must be such that the actual arguments are consistent with the characteristics of the dummy arguments.

In this case the rule seems to be respected, as a is always declared as

real, intent(inout) :: a(:) 

So, what am I missing in the interpretation of the standard that makes the previous code wrong?

Marc
  • 16,170
  • 20
  • 76
  • 119
Massimiliano
  • 7,842
  • 2
  • 47
  • 62

1 Answers1

6

Dummy arguments that are assumed shape must have an explicit interface at their point of reference. F90 12.3.1.1 item 2c.

Practically, assumed shape arrays are passed by passing a descriptor - a little structure that describes the bounds and the location of storage of the array. Ye-olde F77 explicit shape and assumed size arrays are passed simply by passing the address of the first element. Without the explicit interface the compiler doesn't know that it needs to build and pass the descriptor - hence chaos and confusion results.

IanH
  • 21,026
  • 2
  • 37
  • 59
  • Do you know why most compilers (e.g GNU,Intel) by default don't include this particular check in the `-Wall` bundle or in the option that should enforce f90 standard? – Massimiliano Nov 08 '12 at 21:50
  • /warn:all in the case of the Intel compiler includes this check. But the compiler must have seen the definition of the subroutine before it sees the reference. In your code the program unit with the subroutine follows the reference (if you compiled the file again you might see the error). In the general case the reference to the procedure might be in a separate file, perhaps compiled some time before the subroutine itself, on a different machine! Hard to report an error for something that "distant". – IanH Nov 08 '12 at 22:52
  • Just wanted to add my two cents here. I ran into this exact same problem a few months ago. IanH's answer is correct, as you know by now, along with his citation of the F90 standard. What gets me is that I have seen no text book, or even a web site, discuss this. There are plenty of examples of passing arrays in the way you want to do with interfaces and inside modules, but I can't find any statement to the effect that that's the way it *has* to be done .... outside of the F90 standard. Curious. And frustrating. – bob.sacamento Nov 08 '12 at 23:58
  • 2
    Different people learn aspects of the language via different paths, but in terms of the forums I monitor I'd venture that it borders on being a FAQ (perhaps a Frequently Encountered Problem is better terminology?). It is mentioned in the two Fortran texts that I have (Modern Fortran Explained + The Fortran 2003 Handbook, in the latter perhaps not in the most obvious/appropriate place for it) and in the documentation for my primary compiler. Safest path is to always ensure an explicit interface is provided if any F90 feature is used, or better, **always** **use** **modules** where possible. – IanH Nov 09 '12 at 02:04