首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >fortran:检测作为虚拟参数传递的空指针

fortran:检测作为虚拟参数传递的空指针
EN

Stack Overflow用户
提问于 2022-11-30 10:00:49
回答 2查看 71关注 0票数 1

我希望从子例程中检测到,与intent(in)一起传递的虚拟参数实际上是一个空指针:

代码语言:javascript
复制
program testPTR
  
implicit none
  
integer, target :: ii
integer, pointer :: iPtr
  
  iPtr => ii
  iPtr = 2
  
  print *, "passing ii"
  call pointer_detect(ii)
  
  print *, "passing iPtr"
  call pointer_detect(iPtr)
  
  iPtr => null()
  print *, "passing iPtr => null()"
  call pointer_detect(iPtr)
  
contains
                                                                                                                                                                      
  subroutine pointer_detect(iVal)
      implicit none
      integer, intent(in), target :: iVal
      integer, pointer :: iPtr
      character(len = *), parameter :: sub_name = 'pointer_detect'
    
      iPtr => iVal
      if (associated(iPtr)) then
        print *, "Pointer associated. Val=", iVal, ", iPtr = ", iPtr
      else
        print *, "Pointer not associated. Val=", iVal, ", iPtr = ", iPtr
       endif
  
  end subroutine pointer_detect
  
end program

令我惊讶的是,它适用于gfortran-9和gfortran-12。然而,我有几个问题:

  1. 检查的合法性、可移植性和Fortran ish是怎样的?
  2. ,因为某种原因,它在上次打印时没有分段错误,而是打印零并干净地退出:

代码语言:javascript
复制
$ gfortan test.f90
$ ./a.out && echo ok
passing ii
 Pointer associated. Val=           2 , iPtr =            2
 passing iPtr
 Pointer associated. Val=           2 , iPtr =            2
 passing iPtr => null()
 Pointer not associated. Val=           0 , iPtr =            0
ok
$ 

有什么想法吗?谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-11-30 16:43:45

碎片

代码语言:javascript
复制
  iPtr => null()
  print *, "passing iPtr => null()"
  call pointer_detect(iPtr)

违反Fortran标准并使您的程序无效(Fortran 2008,25.5.2.3):

除对内部查询函数的引用外,对应于非可选非指针虚拟参数的指针实际参数应是与目标相关联的指针。

非内在过程的虚拟参数既不是可选的,也不是指针.

避免这个问题的责任完全是程序员和the compiler has no duty为您检测这个坏代码。

但是,如果被要求,编译器很可能能够检测到这样的错误(通常在运行时):

代码语言:javascript
复制
At line 19 of file brokenpointer.f90
Fortran runtime error: Pointer actual argument 'iptr' is not associated

是使用gfortran和-fcheck=pointer编译选项时的输出,或者

代码语言:javascript
复制
forrtl: severe (408): fort: (7): Attempt to use pointer IPTR when it is not associated with a target

和艾弗特的-check pointers

程序员无法在过程本身中可靠地进行类似的检查,因为Fortran编译器没有义务尊重以这种方式破坏规则的程序员。

看看这个过程在这里的努力,例如:

代码语言:javascript
复制
      iPtr => iVal
      if (associated(iPtr)) then

iVal不是指针,因此iPtr将在指针赋值中与该变量相关联。编译器可以假设您没有破坏Fortran的规则,因此iptr是关联的,并且测试条件总是正确的。在没有有效的Fortran程序中,该测试条件可以解析为false。

然而,并非所有的希望都失去了。我引用的标准文本说的不是“非指针”,而是“非可选”。如果iVal是可选的,则使用PRESENT()

代码语言:javascript
复制
  subroutine pointer_detect(iVal)
      implicit none
      integer, intent(in), optional :: iVal
      character(len = *), parameter :: sub_name = 'pointer_detect'
    
      if (present(iVal)) then
        print *, "Actual argument pointer was associated. Val=", iVal
      else
        print *, "Actual argument pointer was not associated."
      endif
  
  end subroutine pointer_detect

如果与不相关的指针实际参数相关联,则非指针、不可分配的可选虚拟参数将被视为不存在。

但是,请注意,如果iPtr具有未定义的关联状态,这将不会对您有所帮助。Nothing will.

票数 3
EN

Stack Overflow用户

发布于 2022-11-30 11:40:48

如果指针为null,则call pointer_detect(iPtr)不符合标准。例程pointer_detect()的名称很差,因为它不能检测到关于原始指针的任何内容,而原始指针根本没有传递:虚拟参数不是指针,因此在调用时编译器将传递iPtr目标的地址,而不是iPtr本身。但是如果iPtr是空的,那么它就没有目标:行为没有定义。

一个未定义的行为是,嗯,未定义的。或者说不可预测。它可能崩溃,或输出不可预测的值,等等.在编译时无法真正检测到这种违反标准的行为,编译器也不需要这样做。但是,gfortran可能有编译选项,可以在运行时进行检测(与任何其他运行时检查一样,性能会受到影响)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74625857

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档