2010-07-08 4 views
1

다음 프로그램이 유효한 C 프로그램입니까?C 표준 라이브러리 코너 사례

#include <stdio.h> 

int main() 
{ 
    fwrite("x", 1, 1, stderr); 
    fflush(stderr); 
    fgetc(stderr); 
    fwrite("y", 1, 1, stderr); 
    return 0; 
} 

stderr에서 읽으려고합니다.

xy 

의미가 있습니다 :

I 2008 Visual C++에서 컴파일 및 실행

, 나는 다음과 같은 출력을 얻을. 그러나 stderr을 파일 ( test.exe 2> foo.txt)로 리디렉션하면 "디버그 어설 션 실패"창이 나타납니다. "일관성없는 스트림 수. 연속 읽기 및 쓰기간에 플러시". 읽기와 쓰기 사이에 fflush을 추가하면 문제가 해결됩니다. (이것은 디버그 빌드에서 발생합니다. 릴리스 빌드에서는 두 번째 쓰기가 자동으로 실패합니다).

이 동작이 정확합니까? 아니면 컴파일러 라이브러리 버그입니까? 읽거나 쓰기가 C. 불법 때 내가 설명 어디서나 어떤 규칙을 찾을 수 없습니다

+4

출력 스트림에서 읽기가 정의되지 않은 동작입니다. 그리고 지구상에서 무엇을 기대합니까? –

+1

컴파일러 버그는 아니지만 라이브러리 구현 버그입니다. –

+1

@NeilButterworth - 출력 스트림을 읽는 것이 UB를 발생시켜야한다고 생각하지 않습니다. Opengroup에 따르면 fgetc가 실패하고 errno를 EBADF로 설정해야합니다 (http://www.opengroup.org/onlinepubs/009695399/functions/fgetc.html 참조). –

답변

3

C99은 7.19.5.3 (fopen)에서 말한다, 제 6 항 :

파일이 업데이트 모드로 열립니다

(위의 mode 인수 목록의 두 번째 또는 세 번째 문자로 '+')를 사용하면 입력 스트림과 출력 스트림을 모두 관련 스트림에서 수행 할 수 있습니다. 그러나 출력은 fflush 함수 [...]에 대한 개입 호출없이 직접 입력 다음에 이어서는 안되며, 입력 연산이 end-end 함수를 만나지 않는 한, 파일 위치 지정 함수에 대한 중간 호출을하지 않고 입력이 출력 바로 뒤에 나오지 않아야한다. of-file.

실제로이 코너 사례를 발견 한 것을 축하드립니다. 라이브러리 구현은 위에서 설명한 을 위반하면이되므로 완전히 맞습니다.

그런데 stderr에서 읽는 것은 드문 일이 아닙니다. 이는 stdinstdout이 리디렉션되고 터미널을 사용할 수없는 경우에 유용합니다. C99에서 읽을 수있는 것은 아니지만 POSIX와 유사한 시스템에서이 작업이 실제로 수행 된 경우를 기억합니다.

+0

이것이 어떻게 문제를 해결하는지 전혀 모르겠습니다. –

+0

99 %의 질문에 답합니다.이론적으로 말미에 "unless"절은 실패한 읽기가 포함되지 않는다는 것을 암시 할 수 있지만, 나는이 경우에 대해 아무도 생각하지 않는다고 생각하므로 정의되지 않았다. – Amnon

+0

@Amnon "파일을 업데이트 모드로 열었을 때"라고 말합니다 - 왜 stderr가 그 모드에서 열렸다고 생각합니까? 그리고 stderr에서 위치 지정 기능을 호출 할 수 없습니다. –

관련 문제