[C++] #pragma once의 unfixable 버그 (번역)

https://stackoverflow.com/questions/1143936/pragma-once-vs-include-guards

#pragma once는 unfixable bug가 있습니다. 사용하지 마세요.

#include의 검색 경로가 충분히 복잡하다면. 컴파일러는 동일한 기본이름의 2개 헤더 사이에서 차이점을 발견하지 못할 수 있습니다. 예를들면 "a/foo.h"와 "b/foo.h" 같은 것들이요.
그래서 한번의 #pragma once 수행시에 2개가 전부 적용될 수 있습니다. 하나는 그냥 묻힌단거죠..

뿐만 아니라 2개의 다른 상대적 include의 경우도 중복포함을 막지 못할 수 있습니다.
예를 들면, #include "foo.h"와 #include "../a/foo.h"는 같은 파일을 참조하므로 #pragma once가 실패할 것입니다.

This also affects the compiler's ability to avoid rereading files with #ifndef guards, but that is just an optimization.
이건 #ifndef 가드로 파일을 다시 읽는 것을 피하는 컴파일러의 능력에도 영향을 미치지만, 그것은 최적화일 뿐입니다.
#ifndef 가드를 사용하면 컴파일러는 아직 본 적이 없는 파일을 안전하게 읽을 수 있습니다. 틀렸을 경우엔, 몇 가지 추가 작업을 해야 합니다.

2개의 헤더가 같은 가드 매크로를 정의하지만 않으면 코드는 기대한대로 컴파일될 거에요.
만약 2개의 헤더가 같은 가드 매크로를 정의했다면, 그것들 중 하나를 바꿔야 하겠죠?

근데 #pragma once는 그런 안전망이 없습니다. 어느  쪽이든 컴파일러가 헤더파일 식별에 대해 뭔가를 틀린다면, 그 프로그램은 컴파일에 실패할겁니다.

이 버그를 고치려면 #pragma once를 사용하지 않거나, 헤더 중 하나의 이름을 바꿔야합니다.
헤더의 이름은 API 계약의 일부이므로, 이름을 바꾸는건 좋은 선택이 아니겠죠.


이 오류의 개선이 불가능한 이유는 유닉스나 윈도 파일 시스템 API 모두 두 개의 절대 경로 이름이 동일한 파일을 참조하는지 여부를 알려주는 어떤 메커니즘도 제공하지 않기 때문입니다. 만약 당신이 inode number가 그걸 위해 사용될 수 있다고 생각한다면, 미안합니다. 당신이 틀렸어요.

Historical note: 제가 GCC에서 '#pragma once'와 '#import'를 찢지 않은 유일한 이유는, ~12년 전, 애플 시스템 헤더가 그들에게 의존했기 때문입니다. 돌이켜보면, 그것이 저를 멈추게 하지 말았어야 했어요..

이제 이 문제가 코멘트 스레드에서 두 번 언급되었으므로: GCC 개발자들은 #pragma를 최대한 신뢰할 수 있게 만들기 위해 상당한 노력을 기울였습니다. GCC bug report 11569를 참조하세요.
그러나, 현재 버전의 GCC에서의 구현은 clock skew로 고통 받는 build farms 같은 그럴듯한 조건하에서 여전히 실패할 수 있습니다. 저는 다른 컴파일러의 구현이 어떤 것인지 모릅니다만, 누가 더 잘 할 거라고 기대하지는 않을 겁니다.

(역주: 해당 답변의 댓글을 보니 의견이 분분한 것 같다. 이미 해결되었다느니 뭐니...)