2

I compile the following program with gfortran -g -fcheck=all -Wall bug.F90:

program main
    implicit none

    real, dimension(:), allocatable :: arr

    allocate (arr(5))
    ! should fail, but happily writes out of bounds
    call foo(arr)

contains

subroutine foo(arr)
    real, dimension(10), intent(inout) :: arr

    arr(10) = 42
end subroutine

end program

When running the program, it doesn't exit with a runtime bounds check error. Why is that the case? Is this a missing feature of gfortran or is there a fundamental reason why doing this would be a bad idea?

I understand that there are situations where reinterpreting an array with a different shape may make sense (and I guess this is allowed in the Fortran standard), for example to go from a 2D array to a flattened 1D array, but in those cases the element count wouldn't change. Reshaping to a lower element count may be fine as well, but definitely not a larger element count, which is what is happening above.

EDIT: To demonstrate that the program is indeed writing to invalid memory addresses I ran it using the electric fence tool:

$ LD_PRELOAD=libefence.so.0.0 ./a.out

  Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <[email protected]>

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7f1f6e42b2da in ???
#1  0x7f1f6e42a503 in ???
#2  0x7f1f6e04ef1f in ???
#3  0x7f1f6ee00885 in foo
        at bug.F90:16
#4  0x7f1f6ee0099d in MAIN__
        at bug.F90:8
#5  0x7f1f6ee009df in main
        at bug.F90:8
Segmentation fault (core dumped)

Similarly, running the program under valgrind gives:

==1162== Invalid write of size 4
==1162==    at 0x108885: foo.3498 (bug.F90:16)
==1162==    by 0x10899D: MAIN__ (bug.F90:8)
==1162==    by 0x1089DF: main (bug.F90:8)
==1162==  Address 0x5e05ae4 is 16 bytes after a block of size 20 alloc'd
==1162==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1162==    by 0x108930: MAIN__ (bug.F90:6)
==1162==    by 0x1089DF: main (bug.F90:8)
7
  • I'm not sure that it does write out of bounds. foo requires a 10-long array, but you only supply a 5-length one. My suspicion, though I might be wrong, is that the binary creates a new 10-long array, copies the first 5 values from arr into it, then runs the subroutine. When it's finished, it copies the first 5 elements back to the main program's arr array. But since the subroutine's arr has length 10, writing to the 10s element is not a bound violation. Commented Nov 6, 2018 at 0:03
  • In fact, I tried it out. If you replace the dimension(10) in the subroutine's declaration section with dimension(:) then you get the bounds violation, because it then gets the size of arr from the argument itself. Commented Nov 6, 2018 at 0:06
  • Writing shape(arr) in the main program and in the subroutine go in that direction: locally, the array has size 10. ifort 18.0.1 (linux x86_64) happily produces the same output. Commented Nov 6, 2018 at 8:10
  • See my edit, there is no copying going on, invalid memory is definitely accessed/written. Commented Nov 6, 2018 at 9:33
  • 3
    The code is wrong there is no doubt about that. This isn't a bounds violation in the access arr(10) but is a failure in the argument association. I'm not aware of a gfortran option for this (otherwise I'd post an answer), but other compilers certainly do offer such run-time checks, Commented Nov 6, 2018 at 9:36

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.