ファイルリダイレクトやパイプを使用してコマンドを提供することは、常に機能するわけではありません。

ファイルリダイレクトやパイプを使用してコマンドを提供することは、常に機能するわけではありません。

このアプリをダウンロードしました2D構築GNU Fortranを使用してコンパイルしますgfortran 9.3.0。 gnu makeを使用してこのプログラムをコンパイルできます。

make

(コンパイル時間:GNU bashを使用してUbuntu 20.04バージョン5.0.17(1)リリース(x86_64-pc-linux-gnu)を実行しているPCで10秒)。

プログラムはパラメータと連携して動作せず、代わりにオプションを手動で入力する必要があります。退屈なワークフローを避けるために、オプションをファイルに書き込みますinstructions.txt

construct2d < instructions.txt

その内容はinstructions.txt次のとおりです。

naca0012.dat
SOPT
NSRF
80
RADI
5
NWKE
5
QUIT
VOPT
JMAX
5
YPLS
5
RECD
1E5
QUIT
GRID
SMTH
QUIT

ファイルは、naca0012.dat圧縮されていないConstruction2Dアーカイブディレクトリにあるか、sample_airfoilsここからダウンロードできます。協会

問題は次のコマンドです。

construct2d < instructions.txt

一度だけ実行すると、期待した結果は出ません。予想される結果を得るには、上記のコマンドを複数回(おそらく4回)実行する必要があります。 (予想出力は次のとおりです。naca0012.p3dおよびnaca0012.nmf

手動で実行してconstruct2dオプションを1つずつ入力すると、期待どおりに機能します。これをデバッグするためにinstructions.txt試しましたが、残念ながら特別な内容は表示されません。gdb

したがって、プログラムがファイルからいくつかの指示を提供するときに、いくつかの指示を無視するようです。なぜこれが起こるのですか?

  • プログラムが期待どおりに実行されると、stdout出力(さらにプログラムは出力ファイルnaca0012.p3dnaca0012.nmf)を生成します。仕事日誌

  • プログラムが期待どおりに実行されないときの標準出力(出力ファイルなし):機能しないログ

あなたの助けに本当に感謝します。

編集1:

Windows 10では、gfortran 8.1.0を使用すると、ファイルのリダイレクトは失敗せずにうまく機能します。前述のように、これはLinuxでのみ発生します。

編集2:行の末尾に関係がないことを確認してください。 Linuxでファイル自体を作成したからですinstructions.txt。ツールを使用してdos2unixファイルをスキャンします。

編集3 以前のバージョンのgfortran(Ubuntu Server 18.04のgfortran 7.5.0)を使用してプログラムをコンパイルしようとしましたが、すべてがうまくいきました。これはGNU Fortranの最新バージョンのバグである可能性があります。

編集4:

フラグを追加したり-Ogプログラムをコンパイルしたときに-O0gfortran 9.xと10.xの奇妙な動作を修正しました。

答え1

comp.lang.fortranの貢献者:

1つの問題はメインループの位置のようです。

  done = .false.
  do while (.not. done)

    call main_menu(command)
    call run_command(command, surf, options, done, ioerror)

  end do

"run_command"を呼び出します。

subroutine run_command(command, surf, options, done, ioerror)
  ...
  logical, intent(out) :: done
  integer, intent(inout) :: ioerror

gfortranは、「ru​​n_command」が「done」値を使用しないため、実際に「done = .false」文を実行することには意味がないと推測しているようです。そして、「run_command」は、「quit」コマンドをチェックしない限り、引数「done」を実際には何も設定しないので、メインループが「done」をチェックしている間、「done」は初期化されていません。時には偽であることもあり、ゴミを含む場合もありますが、この場合は真と評価され、メインループが早く終了します。

「done」の意図を「inout」に変更すると問題が解決するようです。

run_commandの"select case"ステートメントの前に"done"を設定することも機能しているようです。

  done = .false.

  select case (command)
  ...

私の考えでは、これがこの問題を解決する正しい方法であり、コンパイラの動作は私を含む私たちのいくつかにとって驚くべきことですが、実際には正しいと思います。

valgrindがこれを見つけるのを助けました。

別のポスターは次のとおりです。

同様に、次の例は

type(options_type), intent(out) :: opt

menu.f90ファイルで次のように変更する必要があります。

type(options_type), intent(inout) :: opt

あるいは、Intent(out)を持つ引数は、サブルーチンに入ったときに定義されておらず、戻す前にサブルーチンから値を取得しない限り、未定義のままであるため、Intent句を省略する必要があります。

他の提案には、配列の境界をチェックするオプションなどを使用したコンパイルと実行が含まれます。

答え2

以前のバージョンのgfortran(gfortran 7.xおよび8.x)を使用してプログラムをコンパイルしようとしましたが、すべてがうまく機能しました。ただし、最新バージョンのgfortran(9.xおよび10.x)にはまだこの問題があります。ところで、gfortran 9.xと10.xで発生する奇妙な動作をフラグを追加したり、プログラムをコンパイルするときに解決しました-Og-O0

@RoboNerdの答えは、最初にこれが起こる理由を説明します。

関連情報