추적 출력

추적 출력

터미널에서 실행하면 아직 입력이 없는 한 hexdump, , 등과 같은 ^D줄 시작 부분에 있는 단일 항목에 반응 하지 않습니다.catodbc

prompt% hexdump -C
<control-D>
prompt% hexdump -C
hello
<control-D><control-D> # a single ^D won't do
00000000  68 65 6c 6c 6f 0a                                 |hello.|
00000006

나는 이것을 fedora 28과 debian 9에서 재현할 수 있습니다. hexdumpDebian에서 제공 하지만 bsdmainutilsbsd에서는 이런 일이 발생하지 않습니다.

이건 그냥 버그인가요? 이 동작을 나타내는 것으로 알려진 다른 프로그램이 있습니까?

답변1

@JdeBP 감사합니다힌트, 동일한 작업을 수행하는 작은 테스트 케이스를 만들 수 있었습니다 hexdump.

#include <stdio.h>

int main(void){
        char buf[64]; size_t r;
        for(;;){
                printf("eof=%d, error=%d\n", feof(stdin), ferror(stdin));
                r = fread(buf, 1, sizeof buf, stdin);
                printf("read %zd bytes, eof=%d, error=%d\n",
                        r, feof(stdin), ferror(stdin));
                if(!r) return 0;
        }
}

glibc 기반 시스템(일반적인 Linux 데스크탑)에서 실행하는 경우.

prompt$ ./fread-test
eof=0, error=0
<control-D>
read 0 bytes, eof=1, error=0

prompt$ ./fread-test
eof=0, error=0
hello
<control-D>
read 6 bytes, eof=1, error=0
eof=1, error=0
<control-D>
read 0 bytes, eof=1, error=0

bsd, Solaris, busybox(uclibc), android 등에서 실행하는 경우:

prompt$ ./fread-test
eof=0, error=0
hello
<control-D>
read 6 bytes, eof=1, error=0
eof=1, error=0
read 0 bytes, eof=1, error=0

표준에 대한 나의 비전문적인 해석을 바탕으로 보면 다음과 같습니다.허점glibc(GNU C 라이브러리)에서.

~에 대한fread:

각 객체에 대해 fgetc() 함수에 대한 크기 호출이 이루어져야 하며 결과는 객체를 정확히 포함하는 부호 없는 문자 배열에 읽기 순서로 저장되어야 합니다.

~에 대한fgetc:

stream이 가리키는 입력 스트림의 파일 끝 표시기가 설정되지 않은 경우그리고 다음 바이트가 존재하면, fgetc() 함수는 다음 바이트를 얻어야 합니다

eof 표시기가 설정되어 있어도 glibc는 "다음 바이트 가져오기"를 시도하는 것 같습니다.

실제로 그것은실제로는GNU C 라이브러리의 버그는 BSD 또는 musl C 라이브러리에 존재하지 않습니다. 2005년 초에 이미 알려짐. Ulrich Drepper는 2007년에 버그 보고를 종료했지만 버그를 수정하지 않았습니다. 2012년에 논의됨, 이는 다른 C 라이브러리에는 이러한 동작이 없으며 1999년 C 표준은 이에 대해 매우 구체적이며 Solaris는 c99대신 컴파일러로 사용될 때 이를 위한 특별한 메커니즘도 가지고 있습니다 cc.

2018년에 마침내 수정됨. 이 문제는 GNU C 라이브러리 버전 2.28에서 수정되었습니다. 현재 "안정적인" 데비안 버전인 버전 9는GNU C 라이브러리 버전 2.24에 위치, 따라서 버그는 보고된 지 14년이 지난 후에도 계속해서 나타납니다.

GNU C 라이브러리 토론에서 지적했듯이,가능성다른 C 라이브러리(예: musl) 또는 다른 플랫폼의 동작에 관계없이 GNU C 라이브러리의 특성을 요구하는 소프트웨어를 작성하세요. 그러나 위에서 언급한 수년간의 논의 동안 그러한 계획은 확정되지 않았습니다. 일부 프로그램은 이전 GNU C 라이브러리에 의해 손상되어 사용자가 EOF 신호를 두 번 연속 보내야 합니다.가지다hexdump여기에는 다른 사람도 포함됩니다.patchStackOverflow의 2018년.

답변2

추적 출력


read(0, "hello\n", 1024)                = 6
read(0, "", 1024)                       = 0
read(0, "hello\n", 1024)                = 6
read(0, "", 1024)                       = 0
read(0, "", 1024)                       = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 11), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8dd4cef000
write(1, "0000000   h   e   l   l   o  \\n "..., 72) = 72
write(1, "000000c\n", 8)                = 8
exit_group(0)                           = ?
+++ exited with 0 +++

여기에서는 hello «ctrl-d» hello «ctrl-d» «ctrl-d»를 입력했습니다(두 번째 hello는 로그 출력에서 ​​잘립니다). 그래서 이렇게 프로그래밍한 것 같습니다.

추적 실행

  • 두 개의 터미널을 엽니다
  • 첫 번째 유형에서는ll /proc/self/fd/1
  • 두 번째 유형에서는strace hexdump -C 2>/dev/pts/«number-at-end-of-output-of-previous-command»

관련 정보