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 つのステップで発生することを除いて、同じことが起こります。dlog
dexp
G77 がランタイム ライブラリに対して使用する呼び出し規約を設定する際に、何か間違っていることがあるはずです。専門知識が高く評価されます。