用于malloc的非第一个元素的Cray指针

时间:2016-01-15 18:22:04

标签: 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_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呢?有人可以清楚地向我解释这是如何动态分配内存的吗?我更习惯于allocatec++ new陈述...

如果您需要该信息,我会使用ifort进行编译。谢谢你的帮助。

1 个答案:

答案 0 :(得分:3)

[简答]我认为z可以用作nz整数的数组,如果我们忠实地翻译原始代码,将它们分配为

似乎可以。
integer, allocatable :: x1(:), z(:)
allocate( x1( nx1 ), z( nz ) )

由于原始代码中的z索引最多可能达到1000,因此确保nz >= 1000可能更安全。

[长答案]根据这些页面(1234),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的例程(nx1nz整数)获得的物理地址),所以我想只要x1z被赋予适当的值,就可以分配nx1nz这些大小。