Fortran可选参数传递给class(*)形参时present误判问题咨询
Fortran可选参数透传异常问题解答
问题1:调用my_subroutine2的场景下,为什么my_subroutine3会误判可选参数b存在?
这个问题的核心是Fortran可选参数的透传规则和隐式类型转换逻辑:
- 当你把一个可选形参作为实参传递给另一个子程序的可选形参时,只有实参与对应虚参的类型、类型参数、秩完全匹配,原可选参数的
present()状态才会正确透传。 - my_subroutine2中的可选形参b是
real(8)具体类型,而my_subroutine3的可选形参b是class(*)无限制多态类型,二者类型不匹配,编译器会自动生成一个临时的多态封装对象作为实参传递给my_subroutine3。 - 这个临时对象本身是“存在”的,因此my_subroutine3中
present(b)会误返回.true.,但因为原实参b实际不存在,临时对象没有关联有效数据,访问时就会触发指针未关联的运行时错误。
问题2:该问题是否由class(*)类型作为可选形参导致?如果是,为什么主程序调用my_subroutine1的场景无报错?
该问题和class(*)类型相关,但并非class(*)本身的缺陷,而是类型匹配规则导致的差异:
- 首先可以确定问题触发和
class(*)有关:只有当传递的实参需要隐式转换为class(*)多态类型时,才会生成临时对象,破坏可选参数的状态透传。 - my_subroutine1中的可选形参b本身就是
class(*)类型,和my_subroutine3的虚参类型完全匹配,不需要生成临时封装对象,因此原可选参数的present()状态可以直接透传:当主程序不传入b时,透传给my_subroutine3的b仍然是未传入状态,present(b)返回.false.,不会触发非法访问,因此运行正常。
修复方案
你提到的按present(b)分支调用是标准的兼容解决方案,代码示例如下:
! 在my_subroutine2中按分支调用即可彻底解决问题 subroutine my_subroutine2(a, b) implicit none integer, intent(in) :: a real(8), intent(in), optional :: b if (present(b)) then call my_subroutine3(a, b = b) else call my_subroutine3(a) end if end subroutine my_subroutine2
内容的提问来源于stack exchange,提问作者minsuk ji
相关产品推荐
相关产品推荐

