파일 리디렉션이나 파이프를 사용하여 명령을 제공하는 것이 항상 작동하는 것은 아닙니다.

파일 리디렉션이나 파이프를 사용하여 명령을 제공하는 것이 항상 작동하는 것은 아닙니다.

이 앱을 다운로드했습니다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.p3dnaca0012.nmf)

수동으로 실행하고 construct2d옵션을 하나씩 입력하면 예상대로 작동합니다. 이를 디버깅하기 위해 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의 기여자:

한 가지 문제는 메인 루프의 위치인 것 같습니다.

  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"는 "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의 답변은 처음에 이런 일이 발생하는 이유를 설명합니다.

관련 정보