Pointers 用于malloc的非第一个元素的Cray指针
我正在尝试更新一些用Fortran 77编写的旧代码。最终,我的目标是使其符合F90+标准,但目前我仍在努力理解其中的一些细节 我已经添加了Pointers 用于malloc的非第一个元素的Cray指针,pointers,fortran,fortran77,cray-pointers,Pointers,Fortran,Fortran77,Cray Pointers,我正在尝试更新一些用Fortran 77编写的旧代码。最终,我的目标是使其符合F90+标准,但目前我仍在努力理解其中的一些细节 我已经添加了implicit none并明确指定了每个变量,删除了90%的goto语句,使循环更干净,并重新组织了许多其他内容。我目前的问题是,我不完全理解cray指针是如何用来分配内存的。例如,我看到如下情况: integer :: nx1, nz integer :: x1, z pointer ( ptr_x1, x1(1) ) pointer ( ptr_
implicit none
并明确指定了每个变量,删除了90%的goto
语句,使循环更干净,并重新组织了许多其他内容。我目前的问题是,我不完全理解cray指针是如何用来分配内存的。例如,我看到如下情况:
integer :: nx1, nz
integer :: x1, z
pointer ( ptr_x1, x1(1) )
pointer ( ptr_z, z(1000) )
...
ptr_x1 = proprietary_malloc(nx1*SIZEOF_INTEGER)
ptr_z = proprietary_malloc(nz *SIZEOF_INTEGER)
...
proprietary_free(ptr_x1)
proprietary_free(ptr_z)
注意,privative\u malloc
应该是c
的malloc
的包装,带有一些基本的内部内存检查。我非常确信代码应该在退出之前调用free
(原始的F77代码根本不…yikes),因此我将自己添加到上面的示例中
如果我理解正确,在第一个malloc
语句之后,x1
可以用作nx1
整数的数组。但是第二句话之后的z
呢?有人能给我解释清楚这是如何动态分配内存的吗?我更习惯于分配
或c++
新的
语句
我正在使用
ifort
进行编译,以防您需要这些信息。谢谢你的帮助。[简短回答]我认为z
可以用作nz
整数的数组,如果我们忠实地翻译原始代码,就可以将它们分配为
integer, allocatable :: x1(:), z(:)
allocate( x1( nx1 ), z( nz ) )
因为原始代码中z
的索引可能会运行到1000,所以确保nz>=1000
可能更安全
[长答案]根据这些页面(,),类似指针(ptr,a(n1,n2,…)
的声明告诉编译器从ptr
开始作为a(1:n1,1:n2,…)
访问内存;i、 例如,n1
,n2
。。。表示数组维度,而不是起始索引。在下面的示例中,所有a(1)
、b(1)
、c(1)
、d(1)
都映射到池(3)
因此给出(使用gfortran-fcray指针
)
实际上,Cray指针的关联规则似乎与伪参数的关联规则非常相似,例如:
program main
implicit none
integer pool( 5 )
pool = [ 1, 2, 3, 4, 5 ]
call sub( pool(3), pool(3), pool(3), pool(3) )
end
subroutine sub( a, b, c, d )
implicit none
integer a( 5 ), b( 10 ), c( * ), d( 1 )
print *, "a: ", a( 1:5 )
print *, "b: ", b( 1:5 )
print *, "c: ", c( 1:5 )
print *, "d: ", d( 1:5 )
end
这给出了相同的结果。我们注意到,所有a
、b
、c
、d
访问物理分配的内存(池(1:5))之外的内存,因此显示了最后两个元素的垃圾数据。另外,print*,d(1:5)
违反了声明的大小d(1)
,可以使用gfortran-fcheck=all…
等选项进行检查
现在回到OP的程序,
ptr_x1
和ptr_z
是从malloc-like例程(对于nx1
和nz
整数)获得的物理地址,所以我想用这些大小分配x1
和z
可能是可以的,只要nx1
和nz
给出了正确的值。这不是Fortran 77的问题,Cray指针从来都不是标准的。感谢您的有趣讨论。我已经确认了你的测试,它们似乎与我的结果相符。此外,我办公室的某个人能够解释编写指针(ptr_z,z(1000))
背后的原因。显然,这与我们在90年代使用的老式调试器有关。通过在那里写入1000,它告诉调试器前1000个元素应该在堆栈上(因此调试器可以访问),而不是在堆上。现在,这完全不相关,所以是的,我应该能够将其重写为allocate(z(nz))
,并且仍然能够使用任何编译器访问信息。
a: 3 4 5 0 275788968
b: 3 4 5 0 275788968
c: 3 4 5 0 275788968
d: 3 4 5 0 275788968
program main
implicit none
integer pool( 5 )
pool = [ 1, 2, 3, 4, 5 ]
call sub( pool(3), pool(3), pool(3), pool(3) )
end
subroutine sub( a, b, c, d )
implicit none
integer a( 5 ), b( 10 ), c( * ), d( 1 )
print *, "a: ", a( 1:5 )
print *, "b: ", b( 1:5 )
print *, "c: ", c( 1:5 )
print *, "d: ", d( 1:5 )
end