[英]fortran: Detecting null-pointer passed as dummy argument
我想從子程序內部檢測到通過intent(in)
傳遞的虛擬參數實際上是一個 null 指針:
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。 但是我有幾個問題:
$ 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
$
有任何想法嗎? 謝謝!
片段
iPtr => null()
print *, "passing iPtr => null()"
call pointer_detect(iPtr)
違反了 Fortran 標准並使您的程序無效(Fortran 2008,25.5.2.3):
除了對內在查詢函數的引用外,對應於非可選非指針偽參數的指針實際參數應是與目標相關聯的指針。
非內在過程的偽參數既不是可選的,也不是指針。
避免這個問題的責任完全是程序員的,編譯器沒有義務為你檢測這個損壞的代碼。
但是,如果被問到(通常在運行時),編譯器很可能能夠檢測到此類錯誤:
At line 19 of file brokenpointer.f90
Fortran runtime error: Pointer actual argument 'iptr' is not associated
在使用 gfortran 和編譯選項-fcheck=pointer
時是 output ,或者
forrtl: severe (408): fort: (7): Attempt to use pointer IPTR when it is not associated with a target
使用 ifort 的-check pointers
。
程序員不能在過程本身內可靠地進行類似的檢查,因為 Fortran 編譯器沒有義務尊重以這種方式違反規則的程序員。
在這里查看程序的工作,例如:
iPtr => iVal
if (associated(iPtr)) then
iVal
不是指針,因此iPtr
在該指針賦值中與該變量相關聯。 允許編譯器假定您沒有違反 Fortran 的規則,因此關聯了iptr
並且測試條件始終為真。 沒有有效的 Fortran 程序可以將測試條件解析為 false。
然而,並不是所有的希望都破滅了。 我引用的標准中的文字說的不是“非指針”:它說的是“非可選”。 如果iVal
是可選的,請使用PRESENT()
:
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
的關聯狀態未定義,這對您沒有幫助。 什么都不會。
如果指針為 null,則call pointer_detect(iPtr)
不符合標准。例程pointer_detect()
的命名很糟糕,因為它無法檢測到有關原始指針的任何信息,而原始指針根本沒有傳遞:虛擬參數不是指針,所以在調用時,編譯器將傳遞iPtr
的目標地址,而不是iPtr
本身。 但是如果iPtr
是 null 那么它沒有目標:行為未定義。
未定義的行為是未定義的。 或說不可預測。 它可能會崩潰,或者 output 不可預測的值,等等......這種違反標准的行為在編譯時無法真正檢測到,編譯器也不需要這樣做。 不過,gfortran 可能具有啟用運行時檢測的編譯選項(與任何其他運行時檢查一樣,會降低性能)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.