6

範囲を超えて配列を割り当てるプログラムがあり、実行時エラーがスローされることを期待していました。それでもエラーはまったく発生せず、プログラムは宣言されていないメモリへの書き込みに進みます。これを防ぐためのコンパイラオプションはありますか?示されているメモリダンプを使用すると、この範囲の超過が現実のものであることが明らかです。これをキャッチするために変数または引数の仕様を宣言する方法はありますか?明らかにこれは明らかなケースですが、F77派生コードの数千行を維持するように任命された場合、これが起こっている可能性があるかどうかは(私には)必ずしも明確ではありません。

PROGRAM TEST_CODE
IMPLICIT NONE

INTEGER*4 :: R(5)           ! Array of 5

    CALL R_TEST(R, 10)

END PROGRAM

SUBROUTINE R_TEST(R, J)
IMPLICIT NONE

INTEGER*4, INTENT(INOUT) :: R(1)    ! Dummy is array of 1
INTEGER*4, INTENT(IN) :: J
INTEGER*4 :: K

DO K=J-5,J+5            ! K=5..15
    R(K) = K            ! No Runtime Error
END DO

END SUBROUTINE

コンパイラーはIntelFortran2011 XEであり、バイト仕様を使用しているのは、それでINTEGER*4何が得られるかを知っているからです。

ランタイムチェックのコンパイラオプションは次のとおりです。 コンパイラオプション

<code> R</code>変数のメモリ

4

2 に答える 2

5

インテル®コンパイラーは、ポインターと割り当て可能な配列の境界チェックで非常に優れた機能を果たします。コードを少し変更して(以下)、次のようなものでコンパイルする場合:

$ ifort -O0 -debug -traceback -check -ftrapuv TEST_CODE.f90

実行時エラーが発生します。ただし、想定サイズの配列の場合、インテル®コンパイラーは境界をチェックできません。特に暗黙的な入力などを伴うF77コードの場合、メモリリークを見つけるのは簡単ではありません。もう1つの小さなことは、Fortranでは、プログラムは何か意味のあることをしなければならないということです。そうしないと、コンパイラは単に何もしないため、コードを省略します。そのため、最後にプリントを追加しました。

R(:)には小さな問題があります。それは、コンパイラがメモリ内で連続していると想定できないことです。したがって、コンパイラの最適化を行うことはできません。その場合は、割り当て可能な配列を使用するか、連続属性(F2008標準)を使用することをお勧めします。

PROGRAM TEST_CODE
IMPLICIT NONE

INTEGER*4 :: R(5)           ! Array of 5

    CALL R_TEST(R, 10)
    print *,R

END PROGRAM

SUBROUTINE R_TEST(R, J)
IMPLICIT NONE

INTEGER*4, INTENT(INOUT) :: R(:)    ! Dummy is array of 1
INTEGER*4, INTENT(IN) :: J
INTEGER*4 :: K

DO K=J-5,J+5            ! K=5..15
    R(K) = K            ! No Runtime Error
END DO

END SUBROUTINE
于 2012-03-27T00:13:33.010 に答える
4

面白い。gfortran 4.6は、ランタイム添え字エラーを検出します。

At line 18 of file test_code.f90
Fortran runtime error: Index '5' of dimension 1 of array 'r' above upper bound of 1 

しかし、ifortXE12.1.1.246はそうではありません。

編集:インテル®コンパイラーのドキュメントからの回答は次のとおりです。「ダミーの引数である配列の場合、上限が*として指定されている次元、または上限と下限が両方とも1である次元については、下限のみがチェックされます。」また、宣言がR(2)に変更されると、ifortは添え字の間違いも検出します。

この理由は、多くの古いコードが、不明なサイズを示すためにダミー引数配列のサイズに「1」の値を使用していたためです。これは、引数をアドレスと見なす場合に機能しますが、コンパイラがダミー引数のサイズを認識していないため、もちろん添え字チェックが不可能になります。この手法は、新しいコードでは使用しないでください。Fortran 90は、想定形状配列(コロン宣言)などのより優れたオプションを提供します。

したがって、「これが発生する可能性があるかどうか(私には)常に明確ではない」、つまり、レガシーコードがifortによってチェックされていない場合の答えは、(1)または(*)または同じものとして宣言されたプロシージャ引数を探しました複数の次元の1つ以上に対して。

于 2012-03-23T14:32:07.077 に答える