0

C++ と Fortran 77 が混在しており、すべて G77 でコンパイルされています。大部分は C++ ですが、ODE ソルバー DVERK を呼び出し、グローバル C 関数を呼び出して導関数 ( で宣言__stdcall) を取得します。奇妙なSIGSEGVが発生するまで、すべて正常に機能しています。

私はそれを追跡しました、そしてそれは がespそのセグメント境界より下に減少していたからです. これが行われた理由は、DVERK に**演算子が含まれているためです。これは、内部的にはスタック上で値によって渡される 2 つの倍精度値を持つ関数呼び出しであり、16 バイトです。関数は答えを返しますが、次の命令が表示されます。

sub 0x10,%esp

これは、引数をスタックに戻すかのように、スタック ポインターを 16 バイト減らします (?) G77 は関数呼び出しのたびにこれを行うようですが、スタック ポインターは変更されないため、通常は害はありません。ただし、**スタック ポインターがデクリメントされたままの場合、そのコードが十分な回数実行されると、SIGSEGV を取得するまでデクリメントが加算されます。(十分なスタック スペースがある場合、DVERK からのリターンによってクリーンアップされるため、この問題は発生しません。)

a**bコードをに置き換えてみましたが、 の後の 8 バイトと のdexp(dlog(a)*b)後の 8 バイトの 2 つのステップで発生することを除いて、同じことが起こります。dlogdexp

G77 がランタイム ライブラリに対して使用する呼び出し規約を設定する際に、何か間違っていることがあるはずです。専門知識が高く評価されます。

4

1 に答える 1

2

この時代、C や C++ を Fortran に混ぜる方法は、ISO-C_Binding を使用することです。C++ からは、extern C で呼び出します。Fortran では、呼び出されるプロシージャに Fortran ISO C Binding (英語の単語) を使用します。これにより、Fortran は C の呼び出し規約 (ABI) を使用します。そうすれば、コンパイラの内部を理解する必要はありません。これを行うには、gfortran など、g77 よりも最新の Fortran コンパイラを使用する必要があります。gfortran は FORTRAN 77 を完全にコンパイルできます。公式には、ISO-C-Binding は Fortran 2003 の一部です。C++ と既存の FORTRAN 77 の間にラッパーを書くことができます。

ISO-C-Binding を説明する Stackoverflow タグがあります: https://stackoverflow.com/tags/fortran-iso-c-binding/info

于 2014-09-07T00:27:10.820 に答える