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)