我正在尝试使用 来学习 Fortran2018 gfortran。在使用指针时,我注意到似乎没有测试空指针的工具。所以我有两个问题:
更实际地说,在下面的代码片段中:我们如何在执行过程中的任何时刻找出分配给p是否“安全”?allocate(可能会想象一个更复杂的、nullify和语句序列deallocate。)
program test
implicit none
real, pointer :: p
! p = 333.333 ! Segfault, p is neither defined, nor allocated
! Since p is not defined, checking whether it's
! associated to a target gives arbitrary results:
print *, "Start: Pointer p associated? ", associated(p) ! Result: True or False
nullify(p) ! Now p is defined, but `null`
print *, "Nullyfied: …Run Code Online (Sandbox Code Playgroud) 考虑:
program main
real, allocatable, dimension(:) :: foo
integer n
n=10
call dofoo(foo,n,1)
allocate(foo(n))
call dofoo(foo,n,0)
end program main
subroutine dofoo(foo,n,mode)
real foo(n)
integer i,n,mode
if(mode.eq.1)then
n=6
return
endif
do i=1,n
foo(i)=i
enddo
return
end subroutine dofoo
Run Code Online (Sandbox Code Playgroud)
上面的代码有什么问题吗?(它适用于gfortran)我第一次传入一个未分配的数组,但是我没有触及它 - 标准中是否有任何可能导致它以系统相关方式运行的东西?
intent(in)我想知道通过与相应实际参数关联的指针修改虚拟参数是否合法/安全。特别是在子例程调用之前建立指针关联时。
例如,以下内容可以吗(它似乎与 gfortran 一起工作正常)?
program test
implicit none
type compound
integer, allocatable :: A1(:)
integer, pointer :: A2(:,:)
end type compound
type(compound), target :: my
integer :: n=5, i
allocate(my%A1(n**2))
my%A2(1:n,1:n) => my%A1(:)
do i=1,n**2
my%A1(i) = i
end do
do i=1,n
print *, my%A2(i,:)
end do
call assign_A(my)
do i=1,n
print *, my%A2(i,:)
end do
contains
subroutine assign_A(var)
type(compound), intent(in) :: var
var%A2(:,:) = 42
end subroutine
end program test
Run Code Online (Sandbox Code Playgroud)
诀窍是用户定义的类型包含一个指针和一个目标,前者指向后者。它的实例作为传递intent(in),并在子例程中通过指针组件对其进行修改(intent(in)可以修改指针指向的值)。我对它的工作原理感到有点惊讶,但也许这只是编译器缺少诊断。如果我直接改变var%A1那当然会失败。
编辑:上述程序的输出(用 …
我有一个子例程ran_init ( length ),其中一条IF语句工作不正确。
下面的代码是我的原始代码的高度简化版本:
\nMODULE ran_state\nUSE nrtype\nIMPLICIT NONE\n\nINTEGER, PARAMETER :: K4B = SELECTED_INT_KIND ( 9 )\nINTEGER ( K4B ), PARAMETER :: hg = HUGE ( 1_K4B ), hgm = -hg, hgng = hgm - 1\nINTEGER ( K4B ), SAVE :: lenran = 0\n\nCONTAINS\n\nSUBROUTINE ran_init ( length )\nUSE nrtype; USE nrutil, ONLY: nrerror\nIMPLICIT NONE\n\nINTEGER ( K4B ), INTENT ( IN ) :: length\nINTEGER ( K4B ) :: hgt\n\nIF ( length < lenran ) RETURN\nhgt …Run Code Online (Sandbox Code Playgroud) 我想从子例程内部检测到传递的虚拟参数intent(in)实际上是空指针:
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 …Run Code Online (Sandbox Code Playgroud) 我一直在研究一些已有 30 多年历史的 Fortran 代码,试图找出为什么它会因为看似随机的原因间歇性地不起作用。一组输入适用于一个用户,但不适用于另一个用户,使用 -O1 或 -O3 编译时可以工作的代码,但使用 -O2 时会出现段错误,以及其他奇怪的废话。
经过大约一周的时间挑选了 30 年没有碰过的代码,我找到了问题所在——有很多未初始化的变量,而且这些变量中的随机垃圾是否崩溃基本上是随机的整个计划。老实说,我不知道这段代码是如何工作的。
现在我回到客户那里并告诉他们发生了什么事,他们的回答是“如果这是一个问题,为什么代码在过去 30 年里一直有效......?” 这是一个公平的问题——为什么这个代码在过去 30 年里对他们有效?我想我是从那时起第一个从源代码重建它的人,90 年代的 Fortran 编译器是否将堆栈归零或其他什么?为什么几十年前的程序员认为将变量放在赋值运算符的右侧是合理的,而不考虑这些变量是否已首先初始化?
fortran ×6
pointers ×2
c++ ×1
c++-faq ×1
gfortran ×1
if-statement ×1
null-pointer ×1
stack-memory ×1
standards ×1
subroutine ×1
undefined ×1