Bash

使用文件重定向或管道輸入命令並不總是有效

  • September 19, 2020

我已經下載了這個程序construct2d並使用 GNU Fortran 對其進行了編譯gfortran 9.3.0。您可以使用 gnu make 編譯程序:

make

(編譯時間:在我的 PC 上執行 Ubuntu 20.04 和 GNU bash,版本 5.0.17(1)-release (x86_64-pc-linux-gnu) 需要 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可以在sample_airfoils未壓縮的construct2D存檔目錄下找到,也可以從此連結下載。

問題是命令:

construct2d < instructions.txt

當我只執行一次時沒有給出預期的結果,我必須多次執行上面的命令(可能是 4 次)才能得到預期的結果:(預期的輸出是:naca0012.p3dnaca0012.nmf)。

當我construct2d手動執行並instructions.txt一一鍵入選項時,它按預期工作。我試圖用gdb它來調試它,但不幸的是它沒有顯示任何特別的東西。

所以看起來程序在從文件中輸入時忽略了一些指令。為什麼會這樣?

  • 程序按預期執行時的stdout輸出(另外程序會生成輸出文件:naca0012.p3dnaca0012.nmf):working.log
  • 程序未按執行方式執行時的標準輸出輸出(沒有輸出文件):not_working.log

我非常感謝您的幫助。

編輯 1

在 Windows 10 上,使用 gfortran 8.1.0,文件重定向工作得很好,它不會失敗。如上所述,這只發生在 Linux 上。

EDIT2:我確認這與行尾無關。因為我已經instructions.txt在 Linux 上創建了文件本身。並使用dos2unix工具檢查文件。

EDIT3 我嘗試使用舊版本的 gfortran(Ubuntu 伺服器 18.04 上的 gfortran 7.5.0)編譯程序,一切正常。這可能是較新版本的 GNU Fortran 中的錯誤。

編輯 4

我通過添加標誌-Og-O0在編譯程序時解決了 gfortran 9.x 和 10.x 中的奇怪行為。

從貢獻者到 comp.lang.fortran:

一個問題似乎是主循環:

 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 似乎在猜測,由於 ‘run_command’ 從未使用過 ‘done’ 的值,因此實際執行語句 ‘done = .false’ 是沒有意義的。並且由於’run_command’實際上並沒有將其參數’done’設置為任何東西,除非它看到’quit’命令,所以當主循環檢查它時’done’未初始化。有時它是假的,有時它包含垃圾,在這種情況下它被評估為真並且主循環提前終止。

將“完成”的意圖更改為“輸入”似乎可以解決問題。

在 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

或者應該省略意圖子句,因為帶有意圖(out)的參數在進入子程序時變為未定義並保持未定義,除非它在返回之前在子程序中獲取值。

其他建議包括編譯和執行選項以檢查數組邊界等。

我嘗試用​​舊版本的 gfortran(gfortran 7.x 和 8.x)編譯程序,一切正常。但是對於較新版本的 gfortran(9.x 和 10.x),問題仍然存在。但是,我通過添加標誌-Og-O0在編譯程序時解決了 gfortran 9.x 和 10.x 中的奇怪行為。

@RoboNerd 的回答中解釋了首先發生這種情況的原因。

引用自:https://unix.stackexchange.com/questions/609693