오늘 개발을 하다가 디버깅 메시지를 심고 컴파일을 한 뒤 수행을 해보았는데 순서가 보장되지 않는 일이 일어났다.
예제 코드는 아래와 같다.

int main()
{
    fprintf(stdout, "[DEBUG] debug1");
    fprintf(stderr, "print1\n");
}

결과는 아래와 같다. 예상한대로인가? 나는 당연히 디버그 메시지가 먼저 나오리라 생각했는데...

$ ./test
print1
[DEBUG] debug1

아래는 위와 같은 문제를 해결한 코드이다.

int main()
{
    fprintf(stdout, "[DEBUG] debug1\n");
    fprintf(stderr, "print1\n");
}

결과를 보자

$ ./test
[DEBUG] debug1
print1

이제 의도한대로의 결과물이 나왔다. 머가 바뀐것인가? 두개의 코드를 비교해보면 달랑 '\n'이 추가되었다.
이런 현상이 발생한 원인은 stdout과 strerr의 차이에서 비롯된다.

 
표준 출력인 stdout은 버퍼가 꽉 차거나, 개행문자를 만나거나, 프로그램이 종료되거나, sacnf와 같은 입력을 만나는 등 특별한 경우를 제외하고는, 버퍼에 쌓아 놓기 때문에 주의 해야 한다.

다시 작성한 코드에서는 개행문자인 '\n'을 만났기 때문에 의도한대로 출력이 된 것이라고 보인다. fflush 함수를 통해 해결할 수도 있지만 내가 의도한데에는 개행문자만으로 충분하고 그게 맞는듯 하다.

추가로 처음 이 문제를 접했을 당시 컴파일 옵션에 따라 이런식의 문제가 생길 수도 있다고 들었다. 해당 옵션은 지금껏 아무 생각 없이 써오던 '-O[n]' 옵션이다.
-O는 옵티마이저에서 따온듯하고 뒤의 숫자는 레벨을 뜻한다. 0~3까지 있는 줄 알았는데 자료를 찾아보니 더 많은 옵션이 있더라...
해당 옵션에 대해서는 나중에 더 자세히 봐야겠다. 일단은 링크만 해놓기로 하자.
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options