Я компилирую следующую программу с 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
При запуске программы она не завершается с ошибкой проверки границ во время выполнения. Почему это так? Это недостающая особенность gfortran или есть фундаментальная причина, почему это было бы плохой идеей?
Я понимаю, что существуют ситуации, когда может иметь смысл переосмысление массива с другой формой (и я предполагаю, что это разрешено в стандарте Фортрана), например, чтобы перейти от 2D-массива к уплощенному 1D-массиву, но в тех В этом случае количество элементов не изменится. Изменение в меньшем количестве элементов также может быть хорошо, но определенно не большее количество элементов, что и происходит выше.
РЕДАКТИРОВАТЬ: Чтобы продемонстрировать, что программа действительно записывает на недопустимые адреса памяти, я запустил ее с помощью инструмента electric fence :
$ LD_PRELOAD=libefence.so.0.0 ./a.out
Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
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)
Аналогично, запуск программы под valgrind дает:
==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)