STDERR 아래에 "세그먼트 오류" 메시지가 있습니까?

STDERR 아래에 "세그먼트 오류" 메시지가 있습니까?

실행 파일을 실행했습니다.bash

./code > log

모든 printf 문이 로그 파일로 이동하는 동안 터미널에 가끔 오류 메시지가 표시됩니다. 아래와 같이 다시 실행합니다.

./code >& log

이제 가끔 발생하는 오류 메시지도 기록됩니다. 그러나 분할 오류가 있으면 터미널에 계속 표시됩니다. 왜? 메시지를 Segmentation fault (core dumped)로그 파일에 넣으려면 어떻게 해야 합니까 ?


사용자 $bash --version

GNU bash, 버전 4.2.24(1)-릴리스(i686-pc-linux-gnu)

답변1

"세그먼트 오류" 메시지가 stderr에 인쇄되지만 이는 프로그램의 표준 오류가 아니라 쉘의 표준 오류입니다. 쉘은 프로그램이 신호로 인해 종료되었음을 감지하면 이 메시지를 인쇄합니다.

실행 중인 프로그램의 쉘 스크립트 부분 주위에서 stderr를 리디렉션하여 이 메시지를 무음으로 설정할 수 있습니다.

{ ./code; } >&log

답변2

분할 오류는 신호이며, 이를 포착하지 못하면 프로그램이 종료되고 쉘이 이를 표준 오류(프로그램의 표준 오류가 아님)로 인쇄합니다.

이런 일이 발생하면 프로그램이나 쉘은 프로그램이 신호를 포착하도록 하여 특정 조치를 취하거나 쉘이 SIGCHILD 신호를 포착한 다음 하위 프로세스의 종료 상태를 확인할 수 있습니다.

답변3

오류 메시지는 리디렉션되지만 분할 오류가 있는 경우에만 터미널에 표시됩니다. 왜?

Per Giles의 TL/DR: 분할 오류 메시지는 프로그램에서 발생하지 않으므로 stderr이러한 stdout메시지를 리디렉션해도 효과가 없습니다. 분할 오류 메시지는 분할 오류 하위 프로세스를 실행하는 셸에 의해 생성됩니다.

뒤에서 일어나는 일은 하위 프로세스가 종료된 후 쉘이 wait()(또는 waitpid())을 호출하고 해당 응답을 사용하여 하위 프로세스가 신호 수신으로 인해 종료되었는지 확인하는 것입니다.

그렇다면 쉘은 일반적으로 메시지를 인쇄하지만 항상 그런 것은 아닙니다.

trap껍질은 마술처럼 아이에게 죽으라는 신호를 보내지 않는다는 점에 유의하십시오 . 어린이만이 신호를 포착하거나 신호에 의해 사망할 수 있습니다. 자식이 사망하면 부모는 SIGCHLD를 받지만 이는 다른 신호입니다.

오류 메시지를 인쇄하거나 인쇄하지 않는 것 외에도 쉘은 $?나타내는 종료 상태도 설정합니다.

$ ./div_by_0
Floating point exception
$ echo $?
136

0으로 나누기 및 기타 신호에도 동일하게 적용됩니다. 자세한 내용은 을 참조하세요 man 3 wait.

이로 인해 발생하는 한 가지 결과는 자식 프로세스가 프로세스 체인의 마지막 프로세스인 경우에만 메시지를 받게 된다는 것입니다.

예를 들어

$ ./div_by_0
Floating point exception
$ echo | ./div_by_0
Floating point exception
$ ./div_by_0 | wc
0 0 0

Giles에 따르면 명령 출력을 파일로 캡처해도 셸이 메시지를 인쇄하는 것을 막지는 못합니다.

$ { ./div_by_0 ; } > log
Floating point exception
$ { ./div_by_0 ; } >& log
$ cat log
Floating point exception

그러나 명령 출력을 변수로 캡처하면 셸이 메시지를 인쇄하지 못하게 됩니다.

$ a=$(./div_by_0)
$ echo $a
$

변수 또는 파일에 대한 출력을 캡처해도 출력이 $?설정되는 데 방해가 되지 않습니다.

$ { ./div_by_0 ; } >& log
$ echo $?
136
$ a=`{ ./div_by_0 ; }`
$ echo $?
136

오류 메시지로 무엇을 하려는지에 따라 위의 내용이 이미 귀하의 필요에 적합할 수도 있고, $?프로그램을 호출한 후 확인하고 싶을 수도 있습니다.

또한 이를 사용 trap ERR하여 오류를 포착한 다음 동작을 호출하여 $?SIGSEGV, SIGFPE 또는 다른 것과 일치하는지 확인할 수도 있습니다.

예를 들어

$ trap 'exit_code=$?; echo "exit code: $exit_code"; if [[ $exit_code -eq 139 ]]; then echo "segfault"; fi ; if [[ $exit_code -eq 136 ]] ; then echo "div by 0"; fi ;' ERR
$ ./div_by_0
Floating point exception
exit code: 136
div by 0

trap이 기능을 켜면 설정 하기 전에 SIGCHLD트랩 코드가 $?호출되므로 원하는 결과가 나올 가능성이 낮습니다. 잘못된 명령은 "$?" = 0을 반환하는 것으로 나타나고 다음 명령은 0이 아닌 값을 반환하는 것으로 나타납니다.$?

예를 들어

$ ./div_by_0
exit code: 0
Floating point exception
$ ./div_by_1
exit code: 136      <-- this is $? from div_by_0, not from div_by_1
div by 0

관련 정보