空数组的边界检查---各种编译器的行为
Bound checking for empty arrays --- behavior of various compilers
更新 20210914:Absoft 支持确认下面描述的 af95
/ af90
的行为是意外的,确实是一个错误。 Absoft 开发人员将努力解决它。其他编译器在这方面的行为是正确的。感谢@Vladimir F 的回答、评论和建议。
我的印象是 Fortran 对于大小为 0 的数组很酷。但是,对于 Absoft Pro 21.0,我遇到了涉及此类数组的(奇怪的)错误。相比之下,gfortran
、ifort
、nagfor
、pgfortran
、sunf95
和 g95
都对同一段代码感到满意。
下面是一个最小的工作示例。
! testempty.f90
!!!!!! A module that offends AF90/AF95 !!!!!!!!!!!!!!!!!!!!!!!!
module empty_mod
implicit none
private
public :: foo
contains
subroutine foo(n)
implicit none
integer, intent(in) :: n
integer :: a(0)
integer :: b(n - 1)
call bar(a) ! AF90/AF95 is happy with this line.
call bar(b) ! AF90/AF95 is angry with this line.
end subroutine foo
subroutine bar(x)
implicit none
integer, intent(out) :: x(:)
x = 1 ! BAR(B) annoys AF90/AF95 regardless of this line.
end subroutine bar
end module empty_mod
!!!!!! Module ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!! Main program !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program testempty
use empty_mod, only : foo
implicit none
call foo(2) ! AF90/AF95 is happy with this line.
call foo(1) ! AF90/AF95 is angry with this line.
write (*, *) 'Succeed!' ! Declare victory when arriving here.
end program testempty
!!!!!! Main program ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
将这段代码命名为testempty.f90
。然后运行
$ af95 -no-pie -et -Rb -g -O0 -o atest testempty.f90
$ ./atest
这是我机器上发生的事情(Ubuntu 20.04,linux 5.4.0-77-generic,x86_64):
./atest
? FORTRAN Runtime Error:
? Subscript 1 is out of range for dimension 1 for array
? B with bounds 1:
? File testempty.f90; Line 19
? atest, run-time exception on Mon Sep 13 14:08:41 2021
? Program counter: 000000001004324B
? Signal SIGABRT, Abort
? Traceback follows
OBJECT PC ROUTINE LINE SOURCE
libpthread.so.0 000000001004324B raise N/A N/A
atest 00000000004141F3 __abs_f90rerr N/A N/A
atest 000000000041CA81 _BOUNDS_ERROR N/A N/A
atest 00000000004097B4 __FOO.in.EMPTY_MO N/A N/A
atest 000000000040993A MAIN__ 40 testempty.f90
atest 000000000042A209 main N/A N/A
libc.so.6 000000000FD0C0B3 __libc_start_main N/A N/A
atest 000000000040956E _start N/A N/A
所以 af95
被 call bar(b)
惹恼了。使用af90
,结果是一样的。
我使用 gfortran
、ifort
、nagfor
、pgfortran
、sunf95
和 g95
测试了相同的代码。尽管我明确地强加了绑定检查,但他们所有人都对代码非常满意。下面是测试的Makefile
。
# This Makefile tests the following compilers on empty arrays.
#
# af95: Absoft 64-bit Pro Fortran 21.0.0
# gfortran: GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
# ifort: ifort (IFORT) 2021.2.0 20210228
# nagfor: NAG Fortran Compiler Release 7.0(Yurakucho) Build 7036
# pgfortran: pgfortran (aka nvfortran) 21.3-0 LLVM 64-bit x86-64
# sunf95: Oracle Developer Studio 12.6
# g95: G95 (GCC 4.0.3 (g95 0.94!) Jan 17 2013)
#
# Tested on Ubuntu 20.04 with Linux 5.4.0-77-generic x86_64
.PHONY: test clean
test:
make -s gtest
make -s itest
make -s ntest
make -s ptest
make -s stest
make -s 9test
make -s atest
gtest: FC = gfortran -Wall -Wextra -fcheck=all
itest: FC = ifort -warn all -check all
ntest: FC = nagfor -C
ptest: FC = pgfortran -C -Mbounds
stest: FC = sunf95 -w3 -xcheck=%all -C
9test: FC = g95 -Wall -Wextra -fbounds-check
atest: FC = af95 -no-pie -et -Rb
%test: testempty.f90
$(FC) -g -O0 -o $@ $<
./$@
clean:
rm -f *.o *.mod *.dbg *test
问题:
af95
/af90
的行为是否符合标准?
- 我的代码是否包含任何违反 Fortran 标准的内容?
- 一般来说,在 Fortran 代码中包含空数组是否被认为是危险的?有时它们是不可避免的,因为数据大小通常在 运行 时间之前无法确定。
“标准”是指 2003 年、2008 年和 2018 年。
非常感谢您的任何意见或批评。
(在Fortran Discourse上也有同样的问题,希望不要违反这里的规则。)
程序对我来说还不错。零大小的数组在 Fortran 中是完全可能的,尽管我承认我通常没有自动数组——但这只是巧合。
我认为这是 Absoft 编译器或其数组边界检查器中的编译器错误。
更新 20210914:Absoft 支持确认下面描述的 af95
/ af90
的行为是意外的,确实是一个错误。 Absoft 开发人员将努力解决它。其他编译器在这方面的行为是正确的。感谢@Vladimir F 的回答、评论和建议。
我的印象是 Fortran 对于大小为 0 的数组很酷。但是,对于 Absoft Pro 21.0,我遇到了涉及此类数组的(奇怪的)错误。相比之下,gfortran
、ifort
、nagfor
、pgfortran
、sunf95
和 g95
都对同一段代码感到满意。
下面是一个最小的工作示例。
! testempty.f90
!!!!!! A module that offends AF90/AF95 !!!!!!!!!!!!!!!!!!!!!!!!
module empty_mod
implicit none
private
public :: foo
contains
subroutine foo(n)
implicit none
integer, intent(in) :: n
integer :: a(0)
integer :: b(n - 1)
call bar(a) ! AF90/AF95 is happy with this line.
call bar(b) ! AF90/AF95 is angry with this line.
end subroutine foo
subroutine bar(x)
implicit none
integer, intent(out) :: x(:)
x = 1 ! BAR(B) annoys AF90/AF95 regardless of this line.
end subroutine bar
end module empty_mod
!!!!!! Module ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!! Main program !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program testempty
use empty_mod, only : foo
implicit none
call foo(2) ! AF90/AF95 is happy with this line.
call foo(1) ! AF90/AF95 is angry with this line.
write (*, *) 'Succeed!' ! Declare victory when arriving here.
end program testempty
!!!!!! Main program ends !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
将这段代码命名为testempty.f90
。然后运行
$ af95 -no-pie -et -Rb -g -O0 -o atest testempty.f90
$ ./atest
这是我机器上发生的事情(Ubuntu 20.04,linux 5.4.0-77-generic,x86_64):
./atest
? FORTRAN Runtime Error:
? Subscript 1 is out of range for dimension 1 for array
? B with bounds 1:
? File testempty.f90; Line 19
? atest, run-time exception on Mon Sep 13 14:08:41 2021
? Program counter: 000000001004324B
? Signal SIGABRT, Abort
? Traceback follows
OBJECT PC ROUTINE LINE SOURCE
libpthread.so.0 000000001004324B raise N/A N/A
atest 00000000004141F3 __abs_f90rerr N/A N/A
atest 000000000041CA81 _BOUNDS_ERROR N/A N/A
atest 00000000004097B4 __FOO.in.EMPTY_MO N/A N/A
atest 000000000040993A MAIN__ 40 testempty.f90
atest 000000000042A209 main N/A N/A
libc.so.6 000000000FD0C0B3 __libc_start_main N/A N/A
atest 000000000040956E _start N/A N/A
所以 af95
被 call bar(b)
惹恼了。使用af90
,结果是一样的。
我使用 gfortran
、ifort
、nagfor
、pgfortran
、sunf95
和 g95
测试了相同的代码。尽管我明确地强加了绑定检查,但他们所有人都对代码非常满意。下面是测试的Makefile
。
# This Makefile tests the following compilers on empty arrays.
#
# af95: Absoft 64-bit Pro Fortran 21.0.0
# gfortran: GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
# ifort: ifort (IFORT) 2021.2.0 20210228
# nagfor: NAG Fortran Compiler Release 7.0(Yurakucho) Build 7036
# pgfortran: pgfortran (aka nvfortran) 21.3-0 LLVM 64-bit x86-64
# sunf95: Oracle Developer Studio 12.6
# g95: G95 (GCC 4.0.3 (g95 0.94!) Jan 17 2013)
#
# Tested on Ubuntu 20.04 with Linux 5.4.0-77-generic x86_64
.PHONY: test clean
test:
make -s gtest
make -s itest
make -s ntest
make -s ptest
make -s stest
make -s 9test
make -s atest
gtest: FC = gfortran -Wall -Wextra -fcheck=all
itest: FC = ifort -warn all -check all
ntest: FC = nagfor -C
ptest: FC = pgfortran -C -Mbounds
stest: FC = sunf95 -w3 -xcheck=%all -C
9test: FC = g95 -Wall -Wextra -fbounds-check
atest: FC = af95 -no-pie -et -Rb
%test: testempty.f90
$(FC) -g -O0 -o $@ $<
./$@
clean:
rm -f *.o *.mod *.dbg *test
问题:
af95
/af90
的行为是否符合标准?- 我的代码是否包含任何违反 Fortran 标准的内容?
- 一般来说,在 Fortran 代码中包含空数组是否被认为是危险的?有时它们是不可避免的,因为数据大小通常在 运行 时间之前无法确定。
“标准”是指 2003 年、2008 年和 2018 年。
非常感谢您的任何意见或批评。
(在Fortran Discourse上也有同样的问题,希望不要违反这里的规则。)
程序对我来说还不错。零大小的数组在 Fortran 中是完全可能的,尽管我承认我通常没有自动数组——但这只是巧合。
我认为这是 Absoft 编译器或其数组边界检查器中的编译器错误。