GNU编译器处理可分配派生类型组件的行为是否符合Fortran标准?
可分配派生类型组件赋值的编译器行为差异:是未定义行为还是编译器错误?
示例代码
program prog type node integer::val type(node),allocatable::next end type type(node)::a,b allocate(a%next) a%val=1 a%next%val=2 print*,a%val,a%next%val b=a b%val=3 b%next%val=4 print*,a%val,a%next%val deallocate(b%next) print*,a%val,a%next%val end
不同编译器的输出结果
GNU Fortran(gfortran-13.1.0)输出:
1 2 1 4 1 0
Intel Fortran(ifx-2024.1.0)/ NAG Fortran(nagfor-7.1)输出:
1 2 1 2 1 2
行为差异分析
- gfortran表现:执行赋值语句
b=a后,a%next与b%next指向同一块内存。修改b%next%val会同步改变a%next%val;调用deallocate(b%next)后,未释放a%next的内存,仅修改了其内容值。 - Intel/NAG编译器表现:执行
b=a时会完成深拷贝,为b%next分配独立的新内存,对b组件的修改、释放操作不会影响a的对应组件。
结论:gfortran存在不符合标准的错误
Fortran标准明确规定,对包含可分配组件的派生类型执行赋值操作时,必须执行深拷贝:右侧对象的可分配组件会被复制到左侧对象的新分配内存中,两侧可分配组件拥有独立存储。
gfortran将可分配组件按指针方式处理(浅拷贝)的行为,违反了Fortran标准要求。后续对b%next的修改影响a%next、释放b%next后a%next的异常状态,均为非标准实现导致的错误行为,而非标准定义的未定义行为。
内容的提问来源于stack exchange,提问作者V T
相关产品推荐
相关产品推荐

