使用文件重定向或管道輸入命令並不總是有效
我已經下載了這個程序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.p3d
和naca0012.nmf
)。當我
construct2d
手動執行並instructions.txt
一一鍵入選項時,它按預期工作。我試圖用gdb
它來調試它,但不幸的是它沒有顯示任何特別的東西。所以看起來程序在從文件中輸入時忽略了一些指令。為什麼會這樣?
- 程序按預期執行時的stdout輸出(另外程序會生成輸出文件:
naca0012.p3d
和naca0012.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 的回答中解釋了首先發生這種情況的原因。