Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Visual Fortran /check:bounds

Pellegrini__Etienne
2,285 Views

Hello,
I have been looking at the behavior of the check:bounds compiler option, and in particular I read through this forum thread. I had a memory corruption in a program I'm writing (which I fixed now) that I think should have been caught by the run-time check. I adapted an example from the forum thread to demonstrate the behavior:

      program ex

        implicit none

        call modify(5)

      contains

        subroutine modify(n)

          implicit none

          integer :: n
          real(kind=8) :: a(3)

          print*, a(1:n)
          
          CALL modify2(a(1:n),n)

          a(1:n) = 10.5D0

        end subroutine modify

        subroutine modify2(a,n)

          implicit none
          integer :: n
          real(kind=8)  :: a(n)
          
          a(1:n) = 10.0
          print*, a(1:n)

        end subroutine

      end

The behavior I am questioning is: Visual fortran gives me the error "Subscript #1 of the array A has value 4 which is greater than the upper bound of 3" at line 20. I agree that indeed, I go out of bounds at that moment. I understand why I do not get the error at line 30, since I think Fortran allows to pass only parts of arrays and then access the subsequent elements simply because they are contiguous in memory.
However, I do not understand why I do not get a runtime error at line 18: I am explicitely asking Fortran to pass an array of size n=5, when a is only size 3. Should that not result in a warning? Or what is the use of allowing such behavior?

Thanks in advance!
Etienne Pellegrini

EDIT: I am running Intel Parallel Studio XE 2016 Composer, Version 16.0.0046.12

0 Kudos
5 Replies
Steve_Lionel
Honored Contributor III
2,285 Views

As long as you don't actually reference out of bounds in subroutine modify, there will be no error.  But once you're in modify2, all the compiler knows is that you declared the array with dimension 5. Bounds checking doesn't catch every possible error - it is specific to subscript (and substring) references that either fetch or store values.

I can see your point that it would be nice if the argument slice was also checked - sounds like a good feature request. Of course, if you use assumed-shape arrays everywhere, you won't have the chance to get into trouble like this.

0 Kudos
Pellegrini__Etienne
2,285 Views

Thank you for your very quick answer Steve, it's good to see that even retirement doesn't change certain things!
Should I start a new post to make a feature request?

I have a subsequent question: I am not using a whole lot of assumed-shape arrays (started off with legacy code), would I lose any speed by switching my code to assumed-shape arrays? Are there any drawbacks to the switch?

Thanks!
P.S.: just realized I posted in the wrong OS forum... My apologies...

0 Kudos
Steve_Lionel
Honored Contributor III
2,284 Views

Regarding your question on performance, the data I have seen says that in most cases it is not noticeable, especially if you are comparing to adjustable arrays (where you pass the bounds separately). My general position is that you should write the clearest code and don't worry about relative performance unless and until you find it's an issue AND you have used a performance profiler, such as VTune, to see where the bottlenecks really are. If you just guess, you'll almost certainly be wrong.

I would think this thread could serve as a feature request, if Intel folks pick up on it. That you're using Windows isn't relevant to the issues raised here (but watch it for next time!)

0 Kudos
Kevin_D_Intel
Employee
2,285 Views

There was a previous request (here) for this feature that is still outstanding. You can subscribe to this earlier thread to stay informed on the implementation.

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,284 Views

Steve,

>>Of course, if you use assumed-shape arrays everywhere, you won't have the chance to get into trouble like this.

program ex
  implicit none
  call modify(5)
contains
  subroutine modify(n)
    implicit none
    integer :: n
    real(kind=8) :: a(3)
!    print*, a(1:n)
    CALL modify2(a(1:n),n)
    a(1:n) = 10.5D0
  end subroutine modify

  subroutine modify2(a,n)
    implicit none
    integer :: n
    real(kind=8)  :: a(:)
    a(1:n) = 10.0
    print*, a(1:n)
  end subroutine
end

The above code was modified to use assumed shape in modify2. However, the CALL modify2, using a slice that is out of bounds does not error... and produces an array descriptor for use in modify2 that has the extended bounds.

Of course, removing the slice (1:n) from the call corrects the problem as written, however consider

CALL modify2(a(m,n), j)

IOW an arbitrary slice, and an arbitrary offset.

Bounds checking on the slice would be nice to have.

Jim Dempsey

0 Kudos
Reply