C file's orientation.

이전글의 마지막에서 언급했던 문제는 XMLCPP 라이브러리의 문제는 아니었습니다. 정확한 이유는 아직 찾지 못했지만 내용은 대략 다음과 같습니다.

C에서 각 stream들은 orientation이라는 것을 가지고 있습니다. 어떤 stream에 대해 처음 사용된 I/O 함수의 타입에 따라 그 stream은 byte-oriented나 wide-oriented가 됩니다. 일단 orientation이 적용되고 나면 다른 타입의 orientation용 I/O 함수는 적용되지 않습니다. ((C99 7.19.2.4))

이 orientation을 바꿀 수 있는 함수는 frepoen과 fwide 두개뿐입니다.

cin, cout, wcin, wcout과 같이 predefine된 C++ standard stream들은 위와 동일한 규칙을 따릅니다. 간단히 말하자면 char 버전과 wchar_t 버전의 함수들은 섞어서 쓸 수 없다는 얘기지요.

XMLCPP 에서 발생했던 문제는 wcout만을 사용하는데 ascii 범위를 벗어나는 문자를 출력하면 그 문자뿐 아니라 그 이후 아무 것도 출력되지 않는 문제였습니다. 이 경우 exception도 발생하지 않고요. -_-;

다음과 같은 코드로 문제를 재현할 수 있습니다. (g++ 3.4.3, solaris 10-x86)


wcout << L"aaaa" << endl;
wcout << L"한글bbbb" << endl;
wcout << L"cccc" << endl;

// result
aaaa


비슷한 코드로 좀 더 시험을 해보았지요.


wcout << L"aaaa" << endl;
wcout << L"한글bbbb" << endl;
wcout << "cccc" << endl; // changed to byte-string literal

// result
aaaa



wcout << L"aaaa" << endl;
wcout << L"한글bbbb" << endl;
cout << "cccc" << endl; // changed to cout

// result
aaaa
cccc


이 결과를 가지고 제가 해석한 원인은 다음과 같습니다.


  1. 먼저 wcout으로 L"aaaa"를 출력할때 wide-가 아닌 byte-oriented C function을 사용합니다. 이로 인해 내부 file(여기서는 stdout)의 orientation은 byte-로 셋팅됩니다.

  2. 일단 내부 file의 orientation이 byte-로 정해졌으므로 이후 모든 wcout 은 거부되고 cout만 처리됩니다.

  3. 여기서 처음의 wcout은 내부 file의 orientation이 정해지지 않았을 때이므로 그냥 수행되는 것으로 보입니다.



Redhat의 g++에서는 어떤 경우에 대해서도 모든 라인이 출력이 됩니다. 다만 wcout을 사용하는 경우에는 "한글"은 출력되지 않습니다. 이는 shell이 UTF-8을 지원하기 때문입니다. 즉, cout을 쓰면 그냥 8-bit 문자로 간주하여 file에 쓰게 되고 이것은 shell에 의해 UTF-8로 해석됨으로 정상적으로 한글이 보이게 됩니다. 따라서 redhat의 g++은 file의 orientation에 대한 규칙을 지키지 않는 것으로 보입니다.

어떤 것이 standard-ly correct(?)한 것인지 모르겠어서 c.l.c.m.에 일단 질문을 등록해 놓았습니다. :-)

Comments

Popular Posts