You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fortran空数组边界检查:多编译器行为差异及合规性问询

更新 20210914

Absoft技术支持确认,下文所述的af95/af90行为属于非预期bug,Absoft开发团队将着手修复该问题,其余编译器的相关行为均符合规范。感谢@Vladimir F提供的解答、评论与建议。


问题背景

我原本认为Fortran对大小为0的空数组支持良好,但在使用Absoft Pro 21.0时遇到了涉及空数组的异常报错,而相同代码在gfortran、ifort、nagfor、pgfortran、sunf95、g95编译器上均可正常运行。

最小复现代码

! testempty.f90

!!!!!! 触发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运行这行没有问题
call bar(b)  ! AF90/AF95运行这行报错
end subroutine foo

subroutine bar(x)
implicit none
integer, intent(out) :: x(:)
x = 1  ! 无论是否存在这行,调用bar(b)都会触发AF90/AF95报错
end subroutine bar

end module empty_mod
!!!!!! 模块结束 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


!!!!!! 主程序 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
program testempty

use empty_mod, only : foo

implicit none

call foo(2)  ! AF90/AF95运行这行没有问题
call foo(1)  ! AF90/AF95运行这行报错
write (*, *) '运行成功!'  ! 运行到此处说明测试通过

end program testempty
!!!!!! 主程序结束 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

复现步骤与报错信息

将上述代码保存为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如下:

# 该Makefile用于测试不同编译器对空数组的支持情况
#
# 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)
#
# 测试环境:Ubuntu 20.04,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

问题解答

1. af95/af90的上述行为是否符合Fortran标准要求?

不符合。Fortran从95标准开始就明确支持大小为0的空数组,自动数组长度为0属于合法场景,边界检查不应该对长度为0的数组抛出下标越界错误。所有其他主流编译器的一致表现也侧面印证了这一点,Absoft官方也已经确认该行为属于编译器bug,会在后续版本修复。

2. 代码是否存在违反Fortran 2003、2008、2018版标准的内容?

不存在。你的代码完全符合各版本Fortran标准的要求:自动数组的长度声明逻辑合法,向假设形参数组传递空数组的操作符合标准,空数组的赋值操作x=1也符合Fortran对零大小数组的赋值规则(赋值操作不会执行,也不会产生越界)。

3. Fortran代码中使用空数组是否存在风险?

  • 标准层面完全没有风险:空数组是Fortran标准明确支持的特性,所有符合标准的编译器都应该正确处理空数组的声明、传递、赋值、运算等操作,是处理可变规模数据时非常常用的合法特性。
  • 实际使用中唯一的风险来自少数老旧或维护较差的编译器存在的未修复bug,比如这次遇到的Absoft的问题。如果你的代码需要兼容这类存在bug的编译器,可以在涉及空数组传递的位置加简单的长度判断,数组长度为0时跳过对应的子程序调用即可规避问题。

内容的提问来源于stack exchange,提问作者Nuno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 11:36:03