2017-03-08 8 views
5

'UNIX 네트워크 프로그래밍 : 소켓 네트워킹 API'버피 오류 설명을 포함stderr에 쓰기 전에 stdout에서 fflush를 사용해야하는 이유는 무엇입니까? 내가 읽고있다

fflush(stdout);  /* in case stdout and stderr are the same */ 
fputs(buf, stderr); 
fflush(stderr); 

과 예제 코드는 다음 줄이 포함 된 오류 처리 기능을 가지고있다. fflush가 첫 번째 줄의 stdout에 왜 사용되는지 이해할 수 없으며 주석이 왜 그 이유를 설명하는지 이해할 수 없습니다.

답변

11

이것은 버퍼링 때문입니다. Stdout and stderr are usually buffered differently. stdout은 이고, 보통은입니다. 즉 줄 바꿈을 볼 때까지 출력을 표시하지 않습니다. Stderr는 이며, 보통 버퍼링되지 않고 즉시 인쇄됩니다. 생각하면 오류 메시지가 표시됩니다.

그러나 둘 다 같은 장소, 터미널로 이동합니다. 이것이 /* in case stdout and stderr are the same */의 의미입니다. 그들은 보통 있습니다. 그러나 그들은 다르게 버퍼링되기 때문에 순서가 어긋나게 표시 될 수 있습니다.

이 코드를 고려하십시오. 줄 바꿈이 없다는 것에주의하십시오.

This is to stdout. This is to stderr. This is also to stdout. 

를하지만되지 않습니다 :

#include <stdio.h> 

int main() { 
    fprintf(stdout, "This is to stdout. "); 
    fprintf(stderr, "This is to stderr. "); 
    fprintf(stdout, "This is also to stdout. "); 
} 

당신은 출력이 될 것으로 기대 것입니다. 순서가 맞지 않아.

$ ./test 
This is to stderr. This is to stdout. This is also to stdout. 

stderr의 출력이 즉시 표시되고 버퍼링되지 않습니다. stdout은 stdout 버퍼가 개행 문자로 플러시 될 때까지 기다려야합니다. 개행 문자가 없으므로 프로그램이 종료 될 때 플러시됩니다.

stderr을 사용하기 전에 stdout을 플러시하면 버퍼링에 관계없이 출력이 올바른 순서로 제공됩니다.

#include <stdio.h> 
#include <unistd.h> 

int main() { 
    fprintf(stdout, "This is to stdout. "); 
    fflush(stdout); 
    fprintf(stderr, "This is to stderr. "); 
    fprintf(stdout, "This is also to stdout. "); 
} 

$ ./test 
This is to stdout. This is to stderr. This is also to stdout. 

이렇게하면 정상적인 메시지와 함께 오류 메시지가 올바른 순서로 출력됩니다. 이렇게하면 오류 메시지가 프로그램의 어떤 부분에 적용되는지에 대한 혼동을 피할 수 있습니다.

+0

두 번째 예가 잘못되었습니다. '이것은 또한 stdout이다 .'와'이것은 stdout이다 .'는 전환되어야한다. – Qix

+0

'stderr'가 버퍼링되지 않은 채로 낯선 경우, 비슷한 문제가 발생하여이 대답으로 해결되지 않습니다. Pedantically, 쓰기 전에 다른 하나를 플러시. 또는 좋은 예의를 사용하고 [완료되면 플러시] – chux

+1

@Qix 감사. 나는 원래 코드에서 파일 핸들을 섞어 놓았다. – Schwern

1

stdout과 stderr이 동일한 파일을 가리키면 stdout 버퍼에있는 것이 무엇이든 먼저 기록되어야합니다.