2

我编译以下程序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 缺少的功能,还是有根本原因为什么这样做是个坏主意?

我知道在某些情况下重新解释具有不同形状的数组可能是有意义的(我猜这在 Fortran 标准中是允许的),例如从 2D 数组到展平的 1D 数组,但在这些情况下元素计数不会改变。重塑为较低的元素数量也可能很好,但绝对不是较大的元素数量,这就是上面发生的情况。

编辑:为了证明程序确实在写入无效的内存地址,我使用电子围栏工具运行它:

$ 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)
4

0 回答 0