2

既存のFORTRANコードを使用しているときに問題が見つかりました。再割り当てする前にアレイの割り当てを解除する必要があると予想されていましたが、これは必要ではありませんでした。これを行うには今必要ですが、正しく機能しません。

現在の擬似コードはおおよそ次のとおりです。

MODULE mA
  TYPE A
    REAL, DIMENSION(:,:,:), ALLOCATABLE :: array
  END TYPE
  TYPE (A), POINTER :: sw(:)
END MODULE

後で、「配列」のサイズを割り当てるコードがあります。これは、現在2回(これまでは1回だけ)呼び出しています。

...
IF (ALLOCATED(sw(1)%array))  DEALLOCATE(sw(1)%array, STAT=aviFail)

IF (aviFail.EQ.0) ALLOCATE(sw(1)%array(1,2,3), STAT=aviFail)
...

ALLOCATE、DEALLOCATE、およびALLOCATEDの定義を調べたところ、次のことがわかりました。

  1. 2回目は、DEALLOCATEが呼び出されますが、STAT値は「1」です。
  2. 失敗した場合(つまり、正のSTATリターン)、DEALLOCATEは、元の配列をそのままにしておくことを意味します。そうではありません。明らかに正しくクリアされます(少なくともデバッガーによると)。
  3. 障害が発生し、STATが定義されていない場合、DEALLOCATEはプログラムを終了することを意味します。そうではありませんが、次のALLOCATEステートメントはSTAT値「1」で失敗します。

また、最初にDEALLOCATINGを実行せずに、同じ配列でALLOCATEを他の場所で2回誤って呼び出していました。本によると、これはプログラムの終了につながるはずです。これは機能するだけでなく、正しく機能し、2番目のALLOCATEからのSTATリターンは「0」です。

Intel FORTRANはこれらの処理を異なる方法で処理しますか、それともFORTRANはC ++のように仕様を満たすことに煩わしくないのでしょうか?

4

1 に答える 1

3

実装の詳細を見ずに、詳細で的を絞った説明をすることは困難ですが、問題を引き起こしているのはポインタの実装である可能性が高いと思います。ALLOCATEとDEALLOCATEの動作についての「本」の回答は正しいように聞こえますが、割り当て可能な配列を直接操作した場合の動作について説明しました。ALLOCATEとDEALLOCATEは、ポインターを操作するときに機能が異なる場合があります(コンパイラーによって異なります)。最も基本的なレベルでは、ポインタを介してメモリを割り当てるには、より多くの手順が必要です。1)ポインタ用に作成するオブジェクトのタイプ/ディメンションを決定し、2)メモリ内にそのタイプ/ディメンションの名前のないオブジェクトを作成して割り当てます。3)関連付けます。新しいオブジェクトのポインタ。実装、コンパイラに応じて、

この実装でポインターを使用する特別な理由はありますか?そうでない場合は、より単純な通常の割り当て可能なアレイに切り替えて、問題が解決するかどうかを確認することをお勧めします。

プログラムが予期せず終了することなく、誤って2回割り当てと配列を行うことができることについて:これは、ポインターを使用した実装にも関連していると思います。再割り当てするポインタは、すでにメモリ内の場所に関連付けられています。この関連付けにより、コンパイラーが2回目の実行時にALLOCATEステートメントを処理する方法が変わる可能性があります。ポインタがALLOCATEステートメントが要求している次元のメモリ位置にすでに関連付けられている場合、プログラムを終了したりエラーをスローしたりする理由はありません。プログラマーは彼または彼女が求めていたものを正確に手に入れています。

最後に、ALLOCATE / DEALLOCATEステートメントとポインターの関連付け/無効化は異なるコンパイラーによって異なる方法で処理されるため、観察動作が「本」に準拠していないことは驚くべきことではありません。ポインタの実装が本当に必要かどうかを確認し、コーディング時にメモリ管理のベストプラクティスを適用することをお勧めします。

于 2013-05-09T22:12:15.073 に答える