2

我正在尝试编写一个使用数万行 Fortran 77 代码的 C++ 程序,但遇到了一些奇怪的错误。我将三个坐标 (x,y,z) 和三个向量的地址从 C++ 传递到 fortran,然后让 fortran 在初始点上运行一些计算并在三个向量中返回结果。

我在一个 C++ 函数中这样做了几百次,离开那个函数,然后再回来做。它第一次完美运行,但第二次停止返回有用的结果(返回 nan),用于具有正 x 分量的点。

最初它似乎是一个算法问题,除了三件事:

  1. 我运行它的前 200 次它运行良好
  2. 如果我从 fortran 调用它并完全消除 C++,它就可以工作(对于最终程序不可行)
  3. 我尝试将打印语句添加到 fortran 以调试出错的地方,但事实证明,如果我将打印语句添加到特定的子例程(甚至像 PRINT *,'Here' 这样简单的东西),程序甚至在第一次运行。

这就是为什么我认为这与 C 和 fortran 函数/子例程调用之间如何分配和释放内存有关。基本设置如下所示: C++:

void GetPoints(void);

extern"C" { void getfield_(float*,float*,float*,float[],float[],float[],int*,int*); }

int main(void) { GetPoints(); //Works GetPoints(); //Doesn't }

void GetPoints(void) { float x,y,z; int i,n,l; l=50; n=1; x=y=z=0.0; float xx[l],yy[l],zz[l] for(i=0;i<l;i++) getfield_(&x,&y,&z,xx,yy,zz,&n,&l); //Store current xx,yy,zz in large global array }

Fortran:

      SUBROUTINE GETFIELD(XI,YI,ZI,XX,YY,ZZ,IIN,NP)
      DIMENSION XX(NP),YY(NP),ZZ(NP)
      EXTERNAL T89c
      T89c(XI,YI,ZI,XX,YY,ZZ)
      RETURN
      END
!In T89c.f SUBROUTINE T89c(XI,YI,ZI,XX,YY,ZZ) COMMON /STUFF/ ARRAY(100) !Lots of calculations !Calling ~20 other subroutines RETURN END

你们有没有看到我正在创建的任何明显的内存问题?也许 fortran 认为存在但实际上被 C++ 释放的常见块?没有使用打印语句进行调试的能力,也没有时间尝试理解别人的几千行 Fortran 77 代码,我愿意尝试任何你们可以建议或想到的任何事情。

我使用 g++ 4.5.1 编译 C++ 代码和最终链接,使用 gfortran 4.5.1 编译 fortran 代码。

谢谢

**编辑:**

我已经将错误追溯到我出生之前编写的一些晦涩的代码片段。它似乎正在寻找多年来在更新中删除的一些常见变量。我不知道为什么它只影响一个维度,也不知道为什么通过添加打印语句可以复制该错误,但我仍然消除了它。谢谢大家的帮助。

4

2 回答 2

0

您可能会遇到“不合时宜”的错误。Fortran 数组是从 1 开始的,而 C 数组是从 0 开始的。确保传递给 Fortran 的数组大小不小于应有的 1。

编辑:

我想它看起来不错......不过,我会尝试在 C++ 函数中分配 51 个元素,看看会发生什么。

顺便说一句float xx[l];不是标准的。这是一个 gcc 功能。通常你应该在new这里分配内存,或者你应该使用std::vector.

另外,我getfield_对循环中的调用感到困惑。你不应该传递igetfield_吗?

于 2011-04-28T19:48:04.117 回答
0

您应该在子例程中声明XX,YYZZ数组T89c,如下所示:

REAL*4 XX(*)    
REAL*4 YY(*)    
REAL*4 ZZ(*)

C/C++ 通常不应该释放任何 Fortran 公共块。这些就像structs在 C 中一样(即内存在编译时保留,而不是在运行时保留)。

T89c出于某种原因,即使没有上述声明,gfortran 似乎也接受以下内容:

print *,XX(1)

在编译期间,但在执行时出现分段错误。

于 2011-04-28T21:17:07.563 回答