首页 文章

Fortran 77处理C内存分配

提问于
浏览
2

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

我在C函数中这样做几百次,保留该函数,然后再回来再做一次 . 它第一次完美地工作,但第二次通过它停止返回具有正x分量的点的有用结果(返回nan) .

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

  • 我运行前200次完美运行

  • 如果我从fortran调用它并且完全消除C(对于最终程序不可行)它是有效的

  • 我've tried adding print statements to fortran to debug where it goes wrong, but turns out if I add print statments to a specific subroutine (even something as simple as PRINT *,'这里'),程序即使在第一次运行时也开始返回NaNs .

这就是为什么我认为它与如何在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解除了?如果没有使用print语句进行调试的能力,也没有时间尝试理解其他人的Fortran 77代码的几千行,我愿意尝试任何你可以建议或想到的东西 .

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

谢谢

编辑:

我已经将错误跟踪到我出生之前编写的代码中一些不起眼的部分 . 看起来它正在寻找多年来在更新中删除的一些常见变量 . 我不知道为什么它只影响一个维度,也不知道为什么bug可以通过添加print语句来复制,但我已经将其删除了 . 谢谢大家的帮助 .

2 回答

  • 0

    您可能遇到了“off-by-one”错误 . Fortran阵列基于1,而C阵列基于0 . 确保传递给Fortran的数组大小不比它们少1 .

    编辑:

    我想它看起来是正确的......但是,我会尝试在C函数中分配51个元素,只是为了看看会发生什么 .

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

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

  • 0

    您应该在子例程 T89c 中将 XXYYZZ 声明为数组,如下所示:

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

    通常,C / C应该永远不会释放任何Fortran公共块 . 它们类似于C中的 structs (即内存在编译时保留,而不是在运行时保留) .

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

    print *,XX(1)
    

    在编译期间但在执行时我遇到了分段错误 .

相关问题