2

数万行の Fortran 77 コードを使用する C++ プログラムを作成しようとしていますが、奇妙なエラーが発生します。3 つの座標 (x、y、z) と 3 つのベクトルのアドレスを C++ から fortran に渡し、fortran に初期点でいくつかの計算を実行させ、3 つのベクトルで結果を返します。

これを C++ 関数で数百回実行し、その関数を離れてから、戻ってもう一度実行します。1回目は完全に機能しますが、2回目は、正のxコンポーネントを持つポイントに対して有用な結果を返さなくなります(nanを返します)。

最初は、次の 3 つの点を除いて、アルゴリズムの問​​題のように見えます。

  1. 最初の 200 回の実行で完全に動作します
  2. Fortran から呼び出して C++ を完全に排除すると機能します (最終的なプログラムでは実行できません)。
  3. Fortran に print ステートメントを追加してどこが間違っているかをデバッグしようとしましたが、特定のサブルーチン (PRINT *,'Here' のような単純なものでも) に print ステートメントを追加すると、プログラムはファーストラン。

これが、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 }

フォートラン:

      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 コードの数千行を理解しようとする時間もありません。

C++ コードのコンパイルと最終的なリンクには g++ 4.5.1 を使用し、fortran コードのコンパイルには gfortran 4.5.1 を使用しています。

ありがとう

**編集:**

私が生まれる前に書かれたコードのあいまいな部分まで、エラーを追跡しました。何年にもわたる更新で削除された共通変数を探しているようです。なぜ 1 つの次元だけに影響を与えたのか、なぜバグが print ステートメントを追加することで再現可能だったのかはわかりませんが、それにもかかわらず、私はそれを排除しました。助けてくれてありがとう。

4

2 に答える 2

0

次のように、サブルーチン内でも配列としてXXYYを宣言する必要があります。ZZT89c

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

C / C ++は、一般に、Fortran共通ブロックの割り当てを解除してはなりません。これらはstructsCの場合と似ています(つまり、メモリは実行時ではなくコンパイル時に予約されます)。

何らかの理由で、gfortranはT89c、上記の宣言がなくても、以下を受け入れるようです。

print *,XX(1)

コンパイル中ですが、実行するとセグメンテーション違反が発生します。

于 2011-04-28T21:17:07.563 に答える
0

「off-by-one」エラーが発生している可能性があります。Fortran 配列は 1 ベースですが、C 配列は 0 ベースです。Fortran に渡す配列のサイズが、必要なサイズよりも 1 小さくなっていないことを確認してください。

編集:

私はそれが正しいと思います...それでも、何が起こるかを確認するために、C++ 関数に 51 個の要素を割り当ててみます。

ちなみにfloat xx[l];標準ではありません。これは gcc の機能です。通常、newここでメモリを割り当てるか、 を使用する必要がありますstd::vector

getfield_また、ループ内での呼び出しに混乱しています。に渡すべきではありませんigetfield_?

于 2011-04-28T19:48:04.117 に答える