2012-04-13 18 views
6

Fortran .dllと同じソースファイルを使用コンパックビジュアルFortran 6.6CまたはインテルVisual Fortran 12.1.3.300でコンパイルできますIA-32)。問題は、インテルのバイナリでは実行に失敗しますが、Compaqではうまくいきます。私はWindows 7の64ビットシステムで32ビットをコンパイルしています。 .dll呼び出しドライバはC#に書かれています。インテルVisual Fortranでコンパイルされ、コンパックVisual Fortranでコンパイルされた場合にのみサブルーチンコールでスタックオーバーフローが発生する

エラーメッセージは、内部サブルーチンが呼び出されたとき(.dllエントリルーチンから呼び出されたとき)、_chkstk()コールから派生しています。 crpmを除いて同様の変数仕様の

 CALL SRF(den, crpm(i), i, inose, qeff(i), rev(i), 
&    qqmax(i), lvtyp1, lvtyp2, avespd, fridry, 
&    luin, luout, lurtpo, ludiag, ndiag, n, nzdepth, 
&    unit, unito, ier) 

:問題の手順は

SUBROUTINE SRF(den, crpm, icrpm, inose, qeff, rev, 
&    qqmax, lvtyp1, lvtyp2, avespd, fridry, luin, 
&    luout, lurtpo, ludiag, ndiag, n, nzdepth, 
&    unit, unito, ier) 

    INTEGER*4 lvtyp1, lvtyp2, luin, luout, lurtpo, ludiag, ndiag, n, 
&   ncp, inose, icrpm, ier, nzdepth 
    REAL*8 den, crpm, qeff, rev, qqmax, avespd, fridry   
    CHARACTER*2 unit, unito 

と、このように呼ばれる(固定ファイル形式はご容赦)として宣言されている

(SO chkstk()に答えます) qeff,revおよびqqmaxは、i-th要素のみが各呼び出しに使用される配列です。

引数が8kbより大きい場合はスタックの問題が考えられますが、この場合は渡された引数に7 x real(64) + 11 x int(32) + 2 x 2 x char(8) = 832 bitsしかありません。

は、私はモジュールに引数(特に配列)を移動するために本当に熱心に取り組んできましたが、私は同じエラー

error

を得続けます。

インテルの.dllが

intel

dissasemblyあるからコンパックの.dllは誰が何であるか上の任意の提案を提供することができます

compaq

ですからdissasemblyそれを引き起こす、またはそれをどのようにデバッグするのですか?

PS。私は予約されたスタックスペースを数百に増やしてMbとなり、問題は解決しません。私はdissacemblerのchkstk()呼び出しをスキップしようとしましたが、プログラムがクラッシュしました。スタックチェックはアドレス0x354000から開始し、0x2D2000に反復し、ガードページへのアクセスがクラッシュします。スタックボトムアドレスは0x282000です。

+0

どちらのコンパイラオプションを使用していますか?コンパイルを試みると、すべての警告エラーフラグが有効になっていると考えることができます。最初のステップとして、 '-std -check all -warn all、nodec、interfaces、declarations -gen_interfaces -g -C -traceback -fpe0 -fp-stack-check'とifortを使います。 – Chris

+0

私は今までにあなた自身の算術ミスを見つけたと思っていますが、合計832バイトは832ビットでなければなりません。各文字が1バイトで表されることは必ずしもそうではありません。これはコンパイラとプラットフォームによって異なる傾向があります。最新のコンパイラでは、さまざまな '記憶単位'のサイズが、ISO_FORTRAN_ENV組み込みモジュールで定義された定数として使用できます。 –

+0

上記の両方のコメントは、私に何か協力するものです。私はもっ​​と調査します。 'CVF'がキャッチしていないスタックの破損があり、何とかそれを吹き飛ばす可能性があります。多くの開発者が最初に書かれた80年代からそれに触れてきたので、コードには多くのことがあります。 – ja72

答えて

2

あなたはメッセンジャーを撮影しています。 Compaqのコードが_chkstk()を呼び出すのとは異なり、違いはインラインであることです。一般的な最適化。 2つのスニペットの主な違いは以下のとおりです。あなたがここで使用参照

mov eax, 0D3668h 

sub esp, 233E4h 

対値が関数で必要なスタック領域の量です。インテルのコードでは、0xd3668バイト= 865869バイトが必要です。Compaqコードには0x233e4 = 144356が必要です。大きな違いがあります。いずれの場合もかなり大量ですが、インテルが重大になっているので、プログラムは通常1メガバイトのスタックを持っています。それを0.86メガバイト上げてみると、非常に近いところにあり、いくつかの関数呼び出しがネストされ、このサイトの名前が見えています。

あなたが知る必要があるのは、あなたのスニペットに含まれていないためです。インテルが生成した関数がローカル変数のために余裕がある理由です。回避策は、フリーストアを使用して大規模な配列の領域を見つけることです。または、リンカーの/ STACKオプションを使用して、より多くのスタックスペースを要求する(オプション名で推測する)。

+0

ありがとうございました。空きスペースを見つけようと空きスペースを_使用することについて詳しく説明できますか?この配列では、 'REAL * 8 'の18,000,000要素の配列を埋める計算がたくさんあります。 – ja72

+1

私はかなり古いですが、かなり古いです。お気に入りのFortranリファレンスのALLOCATEとDEALLOCATEステートメントを見てください。 –

+0

これらの配列はVBAで割り当てられ、Fortranの '.dll'に渡されます。それらはFortranで割り当てられていないので、割り当て可能な配列は使用できません。私はまだここで答えを探しているので、投稿は非常に役立っています。 – ja72

関連する問題