Best practices for passing and/or declaring lower and upper bounds in subroutine

Hello Everyone,
I’m trying to convert some old F77/f90 subroutines to modern Fortran.
I have this subroutine that in the declaration of inputs has

real    bf(imin:imax,jmin:jmax,kmin:kmax,3)

How can this case be handled?
Apart for adding an intent(inout) statement, I don’t know how to declare the lower and upper bounds of the input array.
When I call this subroutine in my program valgrind detect a read past the array limits, but the compiler gfortran detects nothing and the program crashes at runtime.
Thank you

3 Likes

I assume it looks like this:

subroutine f(imin, imax, jmin, jmax, kmin, kmax, bf)
real    bf(imin:imax,jmin:jmax,kmin:kmax,3)

You can either leave it, or you can do:

subroutine f(imin, jmin, kmin, bf)
! real    bf(imin:,jmin:,kmin:,3)  ! Not sure right now if this is allowed
real    bf(imin:,jmin:,kmin:,:) ! This should work

This would keep the lower bounds and the upper bound would be runtime. Finally, you can also do:

subroutine f(bf)
real    bf(:,:,:,:)

But then the lower bound will be 1.

There is some contrarian thinking reemerging recently with explicit-shape arrays in Fortran which is what you have at the moment. Unfortunately though there is little support for defensive/safe programming against it in the language.

Until that might appear (in a distant future), my personal suggestion will be to follow the route set forth with “modern” Fortran starting with the Fortran 90 standard revision.

Which is to use the combination of explicit interfaces readily achieved via module procedures and also assumed-shape arrays.

Also, to think along the lines of library development as a collection of codes toward a particular “physics” (or math, economics, etc.) problem in what might be a multi"physics" solution/application i.e., many effects get considered together. Then in one or more such collections, it is possible the codes like to work with particular lower bounds that are different from unity. In that case, look at alternate options to achieve such lower bounds such as

  • named constants (parameter attribute) at the MODULE level,
  • module entities that have setter methods (and getter if need be),
  • parameterized derived types where the length/kind type parameter facilitates lower bound handling via a OO “class” type of approach.

Followed by the use of some run-time assertion approach (may be a simple assert subroutine) to ensure the shapes of arrays in the procedures are as expected: see this, it may already be on the anvil with Fortran stdlib

Aside from the higher-level issues already being discussed, I am wondering why gfortran did not trap the error. If not already doing so, are you including compiler options similar to the following?

-Wall -Wextra -Wimplicit-interface  -fcheck=bounds -fcheck=array-temps -fbacktrace 

@certik It turned out, as you said, that leaving
real bf(imin:imax,jmin:jmax,kmin:kmax,3)
was acceptable for the compiler and probably the best solution for future maintenance.
@FortranFan Thank you for your suggestions
@urbanjost I was already using all of them, the error was caught after adding intent(...) to the arguments.
Thanks all

1 Like