用于 malloc 的非第一个元素的 Cray 指针
Cray pointer of non-first element for use in malloc
我正在尝试对一些用 Fortran 77 编写的旧代码进行现代化改造。最终,我的目标是使其与 F90+ 兼容,但目前我仍在尝试理解其中的一些细节。
我已经添加了 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)
请注意,proprietary_malloc
应该是 c
的 malloc
的包装,带有一些基本的内部内存检查。我非常有信心代码 应该 在退出之前调用 free
(原来的 F77 代码根本不会......哎呀),所以我自己将其添加到上面的例子。
如果我理解正确,在第一个malloc
语句之后,x1
可以用作nx1
整数的数组。但是在第二个语句之后 z
呢?有人可以清楚地向我解释这是如何动态分配内存的吗?我更习惯 allocate
或 c++
new
语句...
我正在使用 ifort
进行编译,以防您需要该信息。感谢您的帮助。
[简答]我觉得z
可以作为nz
个整数的数组,如果忠实翻译原文的话,分配成[=45=似乎也可以]
integer, allocatable :: x1(:), z(:)
allocate( x1( nx1 ), z( nz ) )
因为原代码中z
的索引可能运行到1000,所以保证nz >= 1000
.
可能更安全
[长答案] 根据这些页面 (1, 2, 3, 4),像 pointer( ptr, a( n1, n2, ... ) )
这样的声明告诉编译器访问从 ptr
开始的内存,如 a( 1:n1, 1:n2, ... )
;即,n1
、n2
、...表示数组维度而不是起始索引。在下面的示例中,所有 a(1)
、b(1)
、c(1)
、d(1)
都映射到 pool(3)
program main
implicit none
integer pool( 5 )
integer :: a, b, c, d
pointer ( p, a( 5 ) ), ( p, b( 10 ) ), ( p, c( * ) ), ( p, d( 1 ) )
pool = [ 1, 2, 3, 4, 5 ]
p = loc( pool( 3 ) )
print *, "a: ", a( 1:5 )
print *, "b: ", b( 1:5 )
print *, "c: ", c( 1:5 )
print *, "d: ", d( 1:5 )
end
所以给予(gfortran -fcray-pointer
)
a: 3 4 5 0 275788968
b: 3 4 5 0 275788968
c: 3 4 5 0 275788968
d: 3 4 5 0 275788968
的确,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 编写的旧代码进行现代化改造。最终,我的目标是使其与 F90+ 兼容,但目前我仍在尝试理解其中的一些细节。
我已经添加了 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)
请注意,proprietary_malloc
应该是 c
的 malloc
的包装,带有一些基本的内部内存检查。我非常有信心代码 应该 在退出之前调用 free
(原来的 F77 代码根本不会......哎呀),所以我自己将其添加到上面的例子。
如果我理解正确,在第一个malloc
语句之后,x1
可以用作nx1
整数的数组。但是在第二个语句之后 z
呢?有人可以清楚地向我解释这是如何动态分配内存的吗?我更习惯 allocate
或 c++
new
语句...
我正在使用 ifort
进行编译,以防您需要该信息。感谢您的帮助。
[简答]我觉得z
可以作为nz
个整数的数组,如果忠实翻译原文的话,分配成[=45=似乎也可以]
integer, allocatable :: x1(:), z(:)
allocate( x1( nx1 ), z( nz ) )
因为原代码中z
的索引可能运行到1000,所以保证nz >= 1000
.
[长答案] 根据这些页面 (1, 2, 3, 4),像 pointer( ptr, a( n1, n2, ... ) )
这样的声明告诉编译器访问从 ptr
开始的内存,如 a( 1:n1, 1:n2, ... )
;即,n1
、n2
、...表示数组维度而不是起始索引。在下面的示例中,所有 a(1)
、b(1)
、c(1)
、d(1)
都映射到 pool(3)
program main
implicit none
integer pool( 5 )
integer :: a, b, c, d
pointer ( p, a( 5 ) ), ( p, b( 10 ) ), ( p, c( * ) ), ( p, d( 1 ) )
pool = [ 1, 2, 3, 4, 5 ]
p = loc( pool( 3 ) )
print *, "a: ", a( 1:5 )
print *, "b: ", b( 1:5 )
print *, "c: ", c( 1:5 )
print *, "d: ", d( 1:5 )
end
所以给予(gfortran -fcray-pointer
)
a: 3 4 5 0 275788968
b: 3 4 5 0 275788968
c: 3 4 5 0 275788968
d: 3 4 5 0 275788968
的确,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
被赋予正确的值。