Fortran零尺寸数组运行机制及内存写入合法性疑问
Fortran零长度数组与非法内存访问问题解析
先直接给你核心问题的答案:没错,你在第三和第四个案例里的操作,确实存在写入不属于当前数组内存的风险,这属于Fortran标准明确规定的未定义行为。下面结合你的代码细节拆解分析:
案例三:allocate(A(0)) 后赋值 A(0)
当你执行 allocate(A(0)) 时,你得到的是一个零长度数组。按照Fortran的规则,零长度数组没有任何合法的下标——简单说,这个数组里根本没有元素可以访问。
你后续写的 A(0) = 9 本质是越界访问了数组范围外的内存。虽然你的程序碰巧输出了9 Size: 0,但这只是编译器没严格检查的结果,完全不代表这是合法操作:
- 如果你的程序里还有其他变量,这个写入操作很可能会覆盖它们的数据,导致莫名其妙的bug;
- 要是开启了编译器的边界检查选项(比如GCC的
-fcheck=bounds),程序会直接触发运行时错误并终止。
案例四:allocate(A(-4))
Fortran里allocate(A(n))这种单参数写法,默认的索引范围是1:n。当你传n=-4时,1:-4是个空范围(起始下标比终止下标大),所以这也会分配出一个零长度数组,size(A)返回0就是最好的证明。
要是你尝试给A(-4)赋值,和案例三一样,都是在碰不属于这个数组的内存,风险完全相同。而你最后写的allocate(A(-4:-4))才是正确的——明确指定了从-4到-4的索引范围,这样数组才有1个合法元素,访问A(-4)才是安全的。
额外提醒:Fortran数组分配的关键要点
- 用
allocate(A(lower:upper))时,只有lower <= upper才会得到非零长度数组,否则就是零长度数组; - 零长度数组没有可访问的元素,任何对其下标的读写都是未定义行为;
- 如果需要给子程序传“空数组”,分配零长度数组是正确的做法,但绝对不能对它做元素级的读写操作。
内容的提问来源于stack exchange,提问作者Dan Sp.
相关产品推荐
相关产品推荐

