用于 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 应该是 cmalloc 的包装,带有一些基本的内部内存检查。我非常有信心代码 应该 在退出之前调用 free(原来的 F77 代码根本不会......哎呀),所以我自己将其添加到上面的例子。

如果我理解正确,在第一个malloc语句之后,x1可以用作nx1整数的数组。但是在第二个语句之后 z 呢?有人可以清楚地向我解释这是如何动态分配内存的吗?我更习惯 allocatec++ 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, ... );即,n1n2、...表示数组维度而不是起始索引。在下面的示例中,所有 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

这给出了相同的结果。我们注意到所有 abcd 访问超出物理分配的内存(池(1:5)),因此显示垃圾数据最后两个元素。此外,print *, d( 1:5 ) 违反了声明的大小 d(1),可以使用 gfortran -fcheck=all ....

等选项进行检查

现在回到 OP 的程序,ptr_x1ptr_z 获得了从 malloc-like 例程中获得的物理地址(对于 nx1nz 整数), 所以我想用这些大小分配 x1z 可能是可以的,只要 nx1nz 被赋予正确的值。