2011-08-05 22 views
0

私は何度も呼び出される必要があるサブルーチンを持つメインプログラムを持っています。メインプログラムは次のようになります:FortranサブルーチンのStackoverflow

program main 
open output file 
    do i = 1, 20000 
    read parameters par_1, par_2, ..., par_8 
    call subroutine (par_1, .... , par_8) 
    enddo 
end program 

サブルーチンはすべての作業を行い、配列の値を保存しません。それらは主に中間結果を格納するために使用されます。私は20個のアレイの2に問題があることがわかっ

subroutine calcr 
    real, dimension(5000) :: array_1, array_2, .... array_20 
    read temperature into array_1 
    read pH into array_2 
    ... 
    store intermediate results into array_10 
    sotre intermediate results into array_20 
    ... 
    make final calculations 
    write the results to the output file 
    close files from which the data was read (temperature, pH...) 
end subroutine 

:よう

サブルーチンが見えます。これらの2つの配列の次元を2倍にすると、問題なく2回プログラムを実行できます。 プログラムは「プログラム例外配列が超過しました」というエラーメッセージで停止します

ディメンション* 10を取ると、プログラムを10回実行しても同じエラーが発生します。

しかし、私は、ディメンション* 100を取る場合、私はエラーわずか約30回のプログラムを実行して取得することができます - 私はすべての治療以来、問題は嘘かもしれないところ、私は知りません「プログラム例外スタックオーバーフロー」

を同じ方法で2つの配列だけがこの問題を抱えています。 ありがとうございました!

+0

あなたが提供した情報であなたに答えを与えることは不可能です。 –

答えて

2

問題は実際のコードなしで診断するのは難しいです。サブルーチンは、メインプログラムのループとカウンタ、またはサブルーチンを呼び出す回数について何か知っていますか?私はこれらの2つの特別な配列を推測しています。あなたは、メインループのカウンタであるiを使って計算されたインデックスによって要素にアクセスしています。

どのコンパイラを使用していますか? gfortranの場合、配列が範囲外であるかどうかを調べるフラグがあります。つまり、read the answer to this questionです。他のコンパイラでは、同様のフラグが考えられます。これらのフラグを使用してコンパイルすることができます。配列の範囲外の問題がどこで発生しているかについて、より多くの情報を得ることができます。あなたのコンパイラは、この

を「バインドプログラムの例外アレイを超え」と呼んでますが問題を引き起こしたコードの行についての情報を与えません。

ここで私はあなたがやっている何を考えてやってプログラムです:

i =   0 
i =   1 
At line 15 of file test2.f90 
Fortran runtime error: Array reference out of bounds for array 'array_1', upper bound of dimension 1 exceeded (5001 > 5000) 

gfortran -fbounds-check test2.f90 

私は次のような出力が得られますので、同じように、私はこれをコンパイルする場合

module global 
    integer :: nsubcalls=0 ! counter for the number of times stuff() is called 
end module 

subroutine stuff 
    use global 
    integer :: isub 
    integer :: nelements = 5000 
    real,dimension(5000) :: array_1 

    do isub=1,nelements 
    array_1(nsubcalls*nelements+isub) = isub 
    end do 

    nsubcalls = nsubcalls +1 
end subroutine 

program main 

    use global 
    integer :: i 

    nsubcalls=0 
    do i=0,20000 
    print *,"i = ",i 
    call stuff() 
    end do 

end program 

なぜスタックオーバーフローが発生するのかは分かりませんが、最終的にはあなたの配列があまりにも多くを占めていると思いますメモリを開始します。あなたがより多くの情報を提供すれば、私はより多くを助けることができるかもしれません。あなたのコードは実際にどのように見えますか?

2

実際の問題はおそらく「配列境界が超過しました」というエラーです。これはバグ、つまりプログラムが配列外の配列要素にアクセスしようとするコードミスを示しています。不正なメモリアクセスは、他のバグを引き起こす可能性があります。あなたがしなければならないと思っているよりも大きな配列サイズを増やすことは、実際の問題に対する貧弱なパッチです。さらに進める前に、配列境界のバグを解決することをお勧めします。なぜインデックスは<か、配列のサイズより1か大きいか? @ Yannの答えを見てください。

2番目の部分では、10と100の係数でディメンションを増やしていますか?いくつかのオペレーティングシステムは、驚くほど小さなデフォルトスタックサイズを持っています。実際にスタックオーバーフローの問題がある場合は、1)小さな配列を使用するようにプログラムを再設計する、2)スタックサイズを増やす、または3)スタックからヒープに配列を移動する3つのソリューションがあります。方法2はお使いのOSによって異なります。ほとんどのコンパイラは、コードを単一のアレイ(LENとクリーナーかもしれません(LEN)をarray_20する20の配列array_1(LEN)と、またforrt1: severe (170): Program Exception - stack overflow

を参照して、例えば、スタックからすべてのアレイまたは大きな配列のいずれかを移動するためにコンパイルオプション提供します、20)。