返回Fortran类指针的构造函数被重复调用的原因排查
为何返回类指针的Fortran构造函数被调用两次并触发SIGBUS错误?
你的代码在gfortran 11下运行正常,但在14.2.0(Apple M1环境)中出现foo_construct被调用两次、触发SIGBUS内存访问错误的问题,根源在于多态指针函数的写法不符合Fortran标准,新版本编译器的标准合规性处理暴露了这个问题。
问题代码
模块代码:
module test implicit none type :: foo end type contains function make() implicit none class (foo), pointer :: make make => foo_construct() end function function foo_construct() implicit none class (foo), pointer :: foo_construct allocate(foo_construct) write (*,*) 'construct_foo' end function end module
驱动程序:
program test_construct use test implicit none class (foo), pointer :: foo_instant foo_instant => make() deallocate(foo_instant) end program
运行异常输出
% ./test_prog construct_foo construct_foo Program received signal SIGBUS: Access to an undefined portion of a memory object. Backtrace for this error: #0 0x102b5eccf #1 0x102b5dd23 #2 0x18cd7a583 #3 0x102523cff #4 0x102523d57 zsh: bus error ./test_prog
原因分析
在Fortran标准中,返回多态指针的函数不能直接通过make => foo_construct()这种方式赋值。新版本gfortran对标准的执行更严格,会额外生成一次foo_construct调用以处理多态指针的返回语义,导致两次内存分配:
- 第一次调用
foo_construct分配的内存被make引用,最终传递给foo_instant; - 第二次调用分配的内存没有被任何变量持有,成为野指针,同时编译器处理多态指针返回时的错误操作触发了SIGBUS错误。
修复方案
修改make函数,通过临时指针接收返回值后再赋值给函数返回指针:
function make() implicit none class (foo), pointer :: make class (foo), pointer :: temp_ptr temp_ptr => foo_construct() make => temp_ptr end function
或者直接在make函数内完成对象分配,避免嵌套的指针返回函数:
function make() implicit none class (foo), pointer :: make allocate(make) write(*,*) 'construct_foo' end function
修改后,foo_construct只会被调用一次,内存错误也会消失。
内容的提问来源于stack exchange,提问作者user1139069
相关产品推荐
相关产品推荐

