【发布时间】:2014-05-27 14:09:52
【问题描述】:
我们正在尝试接管 C++ 中遗留 Fortran 代码(+100,000 行代码)的内存分配,因为我们使用 C 库在集群上分区和分配分布式内存。可分配变量在模块中定义。当我们调用使用这些模块的子程序时,索引似乎是错误的(移动了一个)。但是,如果我们将相同的参数传递给另一个子程序,我们会得到我们期望的结果。以下简单示例说明了这个问题:
你好.f95:
MODULE MYMOD
IMPLICIT NONE
INTEGER, ALLOCATABLE, DIMENSION(:) :: A
SAVE
END MODULE
SUBROUTINE TEST(A)
IMPLICIT NONE
INTEGER A(*)
PRINT *,"A(1): ",A(1)
PRINT *,"A(2): ",A(2)
END
SUBROUTINE HELLO()
USE MYMOD
IMPLICIT NONE
PRINT *,"A(1): ",A(1)
PRINT *,"A(2): ",A(2)
CALL TEST(A)
end SUBROUTINE HELLO
main.cpp
extern "C" int* __mymod_MOD_a; // Name depends on compiler
extern "C" void hello_(); // Name depends on compiler
int main(int args, char** argv)
{
__mymod_MOD_a = new int[10];
for(int i=0; i<10; ++i) __mymod_MOD_a[i] = i;
hello_();
return 0;
}
我们正在编译:
gfortran -c hello.f95; c++ -c main.cpp; c++ main.o hello.o -o main -lgfortran;
运行 ./main 的输出是
A(1): 1
A(2): 2
A(1): 0
A(2): 1
您可以看到 A 的输出是不同的,尽管两个子例程都打印了 A(1) 和 A(2)。因此,HELLO 似乎从 A(0) 而不是 A(1) 开始。这可能是因为 ALLOCATE 从未在 Fortran 中直接调用过,因此它不知道 A 的边界。有什么变通方法吗?
【问题讨论】:
-
假定形状数组定义为你的
INTEGER A(*)总是从 1 开始,这与它们的分配无关。这里适用的是参数传递规则。 -
但是,请理解你在这里玩火,我会使用指针,而不是可分配的。
-
玩火是对的 :) 此外,带有指针指定的类型成员也是嵌入在类型中的 fortran 描述符,但具有不同的标志,并且末尾没有维度记录(因为它 将指向完全定义值的东西。
-
我不这么认为。当您在您的整个数组操作之一中遇到具有自动左侧重新分配功能的编译器时,这将开始变得有趣。调试愉快。
-
无论如何,字符串都会发生这种情况,而且一点也不好笑 :) 我查看了 fortran start-of-subroutine 汇编的大量行,以找出为什么会发生很多非常奇怪的事情。
标签: c++ fortran mixed-code allocatable-array