【发布时间】:2011-04-28 19:14:46
【问题描述】:
我正在尝试编写一个使用数万行 Fortran 77 代码的 C++ 程序,但遇到了一些奇怪的错误。我将三个坐标 (x,y,z) 和三个向量的地址从 C++ 传递到 fortran,然后让 fortran 在初始点上运行一些计算并在三个向量中返回结果。
我在一个 C++ 函数中这样做了几百次,离开那个函数,然后再回来做。它第一次完美运行,但第二次停止返回有用的结果(返回 nan),用于具有正 x 分量的点。
最初看起来像是一个算法问题,除了三件事:
- 前 200 次运行它运行良好
- 如果我从 fortran 中调用它并完全消除 C++,它就可以工作(对于最终程序不可行)
- 我曾尝试将打印语句添加到 fortran 以调试出错的地方,但结果表明,如果我将打印语句添加到特定子例程(甚至像 PRINT *、'Here' 这样简单的子程序),程序开始返回 NaN即使是第一次运行。
这就是为什么我认为这与 C 和 fortran 函数/子例程调用之间的内存分配和释放方式有关。基本设置如下所示:
C++:
void GetPoints(void);
外部“C” { void getfield_(float*,float*,float*,float[],float[],float[],int*,int*); }
int main(void) { 获取点(); //作品 获取点(); //没有 }
void GetPoints(void)
{
浮动 x,y,z;
整数 i,n,l;
l=50;
n=1;
x=y=z=0.0;
浮动 xx[l],yy[l],zz[l]
对于(i=0;i<l;i++)
getfield_(&x,&y,&z,xx,yy,zz,&n,&l);
//将当前的xx,yy,zz存储在大的全局数组中
}
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++ 释放的常见块?由于无法使用 print 语句进行调试,也没有时间尝试理解别人的几千行 Fortran 77 代码,我愿意尝试任何你们可以建议或想到的任何事情。
我使用 g++ 4.5.1 编译 C++ 代码和最终链接,使用 gfortran 4.5.1 编译 fortran 代码。
谢谢
**编辑:**
我已将错误追溯到我出生之前编写的一些晦涩难懂的代码片段。它似乎正在寻找多年来在更新中删除的一些常见变量。我不知道为什么它只影响一个维度,也不知道为什么通过添加打印语句可以复制该错误,但我仍然消除了它。谢谢大家的帮助。
【问题讨论】:
-
l是否应该未初始化?这不是真正的 C++——在 C++ 中的堆栈上创建的数组必须在编译时指定它们的大小,而不是通过变量——你使用的是 C/g++ 扩展。但我不认为这是你的问题。 -
啊,对不起,应该初始化(并且在真实代码中)。我也尝试过使用整数大小进行初始化,没有任何变化。
-
您确定您已将 Fortran 编译为使用 C 风格的函数调用协议吗? Fortran77 没有固有的堆栈概念。
-
我对此并不肯定。是否有特定的编译标志?我有 -lg2c,但那是因为如果我没有它会抱怨,我不完全确定它涵盖的所有内容。
-
1.你试过调试器吗? 2. 您是否在启用所有运行时检查的情况下编译了 fortran 代码 (
-fcheck=all)?
标签: c++ g++ memory-management gfortran fortran77