向具有 TARGET 属性的虚拟参数的过程提供不具有 TARGET 属性的参数
Providing an argument that has not the TARGET attribute to a procedure with a dummy argument that has the TARGET attribute
在 Fortran 语言中,向具有 TARGET 属性的虚拟参数的过程提供不具有 TARGET 属性的参数应该会导致无效代码。但是,当使用 gfortran (5.1.0) 或 ifort (14.0.0) 编译以下代码时,未检测到错误,程序的行为就像参数实际上具有 TARGET 属性一样。当我说它是无效代码或者这是编译器缺陷时,我错了吗?
program pointerization
implicit none
integer, dimension(3) :: A
integer, dimension(:), pointer :: ptr_A
A = [1, 2, 3]
call pointerize(A, ptr_A)
print*, "A=", ptr_A
contains
subroutine pointerize(tab, ptr_tab)
integer, dimension(:), intent(in), target :: tab
integer, dimension(:), pointer :: ptr_tab
ptr_tab => tab
end subroutine
end program
您说得对,您的代码无效。不过,并不是因为你说的原因。
在过程中,伪参数具有目标属性是合法的,即使关联的实际参数没有。本质上,只要该指向的生命周期不超过过程的生命周期,我们就可以在过程中使用指向实体的指针。
在这个问题的情况下,伪参数 tab
被允许具有目标属性,即使关联的实际参数 A
没有。甚至过程中的指针赋值语句ptr_tab => tab
也是合法的
然而,重要的是在过程之外,实际参数没有目标属性,我们无法通过指针影响该实体。 Fortran 标准通过以下方式确保不会发生这种情况(Fortran 2008 C.9.4,另请参见 12.5.2.4;Fortran 2018 中存在类似情况):
If a nonpointer dummy argument has the TARGET attribute and the corresponding actual argument does not, any pointers that become associated with the dummy argument, and therefore with the actual argument, during
execution of the procedure, become undefined when execution of the procedure completes.
也就是说,在问题的情况下,完成pointerize
ptr_A
不再是已定义的关联状态。不允许在主程序的打印语句中引用此指针。
出于兴趣,使用 nagfor 编译示例代码会导致 运行 时间诊断
Runtime Error: aaa.f90, line 9: Reference to dangling pointer PTR_A
Target was RETURNed from procedure POINTERIZATION:POINTERIZE
Program terminated by fatal error
Abort (core dumped)
但同样,仅仅因为指针关联未定义,并不意味着您无法获得预期的结果。这种检查对编译器来说是一件好事,但并不要求它一定会失败。
在 Fortran 语言中,向具有 TARGET 属性的虚拟参数的过程提供不具有 TARGET 属性的参数应该会导致无效代码。但是,当使用 gfortran (5.1.0) 或 ifort (14.0.0) 编译以下代码时,未检测到错误,程序的行为就像参数实际上具有 TARGET 属性一样。当我说它是无效代码或者这是编译器缺陷时,我错了吗?
program pointerization
implicit none
integer, dimension(3) :: A
integer, dimension(:), pointer :: ptr_A
A = [1, 2, 3]
call pointerize(A, ptr_A)
print*, "A=", ptr_A
contains
subroutine pointerize(tab, ptr_tab)
integer, dimension(:), intent(in), target :: tab
integer, dimension(:), pointer :: ptr_tab
ptr_tab => tab
end subroutine
end program
您说得对,您的代码无效。不过,并不是因为你说的原因。
在过程中,伪参数具有目标属性是合法的,即使关联的实际参数没有。本质上,只要该指向的生命周期不超过过程的生命周期,我们就可以在过程中使用指向实体的指针。
在这个问题的情况下,伪参数 tab
被允许具有目标属性,即使关联的实际参数 A
没有。甚至过程中的指针赋值语句ptr_tab => tab
也是合法的
然而,重要的是在过程之外,实际参数没有目标属性,我们无法通过指针影响该实体。 Fortran 标准通过以下方式确保不会发生这种情况(Fortran 2008 C.9.4,另请参见 12.5.2.4;Fortran 2018 中存在类似情况):
If a nonpointer dummy argument has the TARGET attribute and the corresponding actual argument does not, any pointers that become associated with the dummy argument, and therefore with the actual argument, during execution of the procedure, become undefined when execution of the procedure completes.
也就是说,在问题的情况下,完成pointerize
ptr_A
不再是已定义的关联状态。不允许在主程序的打印语句中引用此指针。
出于兴趣,使用 nagfor 编译示例代码会导致 运行 时间诊断
Runtime Error: aaa.f90, line 9: Reference to dangling pointer PTR_A
Target was RETURNed from procedure POINTERIZATION:POINTERIZE
Program terminated by fatal error
Abort (core dumped)
但同样,仅仅因为指针关联未定义,并不意味着您无法获得预期的结果。这种检查对编译器来说是一件好事,但并不要求它一定会失败。