ifort关联派生类型指针时associated函数意外返回false问题
Fortran中
associated(ptr, target)在ifort下返回false的问题分析与解决 我编写了一段Fortran程序,将指针关联到派生类型实例后,用associated()函数检测指针是否与目标对象关联。使用gfortran 9.2.0编译时,associated()按预期返回true;但用ifort 19.0.4.243编译时,带目标参数的associated(ptr, obj)返回false。
程序代码
module mod_pointer_association type mytype end type mytype contains subroutine test_association(obj) class(mytype), target, intent(in)::obj class(mytype), pointer::ptr ptr=>obj if (.not. associated(ptr)) then print *, "ptr not associated" error stop end if if (.not. associated(ptr, obj)) then print *, "ptr not associated with obj" error stop end if end subroutine test_association end module mod_pointer_association program test_pointer_assocation use mod_pointer_association type(mytype), target::myobj call test_association(myobj) end program test_pointer_assocation
运行结果
- gfortran编译运行无输出,符合预期;
- ifort编译运行输出:
$ ./test_pointer_association ptr not associated with obj
问题原因
这个问题源于ifort对多态对象指针关联检测的处理逻辑:当obj是class(mytype)类型的多态哑元时,ifort在参数传递过程中会对多态实参执行装箱操作,创建临时对象,导致子例程内obj的内存地址与原始对象myobj的地址不一致。而ptr关联的是原始对象的地址,因此associated(ptr, obj)会返回false。
解决方案
有三种可行的解决方式:
- 改用多态指针作为子例程哑元
将子例程的哑元改为多态指针类型,直接传递原始对象的指针,避免临时对象的创建。修改后的代码如下:
module mod_pointer_association type mytype end type mytype contains subroutine test_association(obj_ptr) class(mytype), pointer, intent(in)::obj_ptr class(mytype), pointer::ptr ptr=>obj_ptr if (.not. associated(ptr)) then print *, "ptr not associated" error stop end if if (.not. associated(ptr, obj_ptr)) then print *, "ptr not associated with obj" error stop end if end subroutine test_association end module mod_pointer_association program test_pointer_assocation use mod_pointer_association type(mytype), target::myobj class(mytype), pointer::obj_ptr obj_ptr => myobj call test_association(obj_ptr) end program test_pointer_assocation
- 通过地址比较替代
associated()
引入iso_c_binding模块,使用c_loc()函数获取指针地址,直接比较地址是否一致:
module mod_pointer_association use iso_c_binding type mytype end type mytype contains subroutine test_association(obj) class(mytype), target, intent(in)::obj class(mytype), pointer::ptr ptr=>obj if (.not. associated(ptr)) then print *, "ptr not associated" error stop end if if (.not. (c_loc(ptr) == c_loc(obj))) then print *, "ptr not associated with obj" error stop end if end subroutine test_association end module mod_pointer_association program test_pointer_assocation use mod_pointer_association type(mytype), target::myobj call test_association(myobj) end program test_pointer_assocation
- 升级ifort版本
较新版本的ifort(如2021及以后)已经修复了这个多态对象指针关联检测的bug,升级编译器后原始代码即可正常运行。
内容的提问来源于stack exchange,提问作者jhaiduce
相关产品推荐
相关产品推荐

