프로젝트에서 위험을 고려할 때 -I 포함 스위치를 사용하는 이유는 무엇입니까?
의 중.-I
GCC에서 전환하면 명령줄 오버라이드 시스템에서 이를 사용하는 것이 다음을 포함한다는 사실에 다소 충격을 받습니다.전처리기 문서에서
"사용할 수 있습니다.
-I
이 디렉토리들은 표준 시스템 헤더 파일 디렉토리보다 먼저 검색되기 때문에 자신의 버전을 대체하여 시스템 헤더 파일을 덮어씁니다."
그들은 거짓말을 하는 것 같지 않습니다. 두 다른 에서 GCC 7른 Ubuntu endian.h
:
#error "This endian.h shouldn't be included"
에 ...을.그리고 같은 디렉토리에 A를 생성합니다.main.cpp
는 main.c,이):
#include <stdlib.h>
int main() {}
그다음에 다음과 같이 컴파일합니다.g++ main.cpp -I. -o main
같은 는 랑,이)다를 .
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:194:0,
from /usr/include/stdlib.h:394,
from /usr/include/c++/7/cstdlib:75,
from /usr/include/c++/7/stdlib.h:36,
from main.cpp:1:
./endian.h:1:2: error: #error "This endian.h shouldn't be included"
에는 이 되어 있는데,에는 stdlib이라고만 있습니다.h에는 이 type.h 파일이 포함되어 있는데, 194번 라인에서는 그냥 이렇게 말합니다.#include <endian.h>
가 분명히 잘못 있었던 것)은 제가 분명히 잘못 알고 있었던 것(그리고 아마도 다른 사람들의 그것)은 각괄호가 이것을 막았을 것이라는 것이었습니다. 하지만 저는 생각했던 것보다 강합니다.
충분히 강하지는 않지만 /usr/include를 명령줄에 먼저 삽입하여 수정할 수도 없기 때문에 다음과 같은 이유가 있습니다.
또는 가 포함된 경우"
-isystem
, 됩니다.-I
,-I
는) 무시됩니다option은됩니다.디렉터리는 여전히 검색되지만 시스템 내 정상 위치에 있는 시스템 디렉터리에는 체인이 포함됩니다."
, 에 대한 .g++ -v main.cpp -I/usr/include -I. -o main
e를 의 맨 usr을를)다.
#include "..." search starts here:
#include <...> search starts here:
.
/usr/include/c++/7
/usr/include/x86_64-linux-gnu/c++/7
/usr/include/c++/7/backward
/usr/lib/gcc/x86_64-linux-gnu/7/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
깜짝 놀랄 정도로.이것을 질문으로 삼아야겠군요.
이 극도로 심각한 문제를 고려할 때 대부분의 프로젝트가 사용해야 할 정당한 이유는 무엇입니까?시스템에서 부수적인 이름 충돌에 따라 임의 헤더를 재정의할 수 있습니다.거의 모든 사람들이 사용해야 하지 않나요?-iquote
대신에?
입니까에는 ?-I
이상-iquote
?-I
(적어도 POSIX에 의해) 표준화되어 있습니다.-iquote
아닙니다. (사실은, 제가 사용하고 있는 건-I
왜냐하면 중 는 tinycc나)입니다를입니다.-iquote
.)
: -I
위험을 고려했을 때?을 디렉토리에 래핑한 다음 -I를 사용하여 해당 디렉토리를 포함하는 디렉토리를 추가합니다.
- 파일 :
includes/mylib/endian.h
- :
-Iincludes
- C/C++ :
#include "mylib/endian.h" //or <mylib/endian.h>
에서 만 하지 .mylib
한 name,다한).
GCC로 .-iquote
그리고 다른 옵션들은 GCC 4에서만 추가되었습니다: https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Directory-Options.html#Directory%20Options .
의 ."-I"
습관, 게으름, 역호환성, 새로운 옵션에 대한 무지, 다른 컴파일러와의 호환성.
해결책은 헤더 파일을 하위 디렉토리에 배치하여 "네임스페이스"하는 것입니다.를 들어 에 넣습니다."include/mylib/endian.h"
그다음에 추가합니다."-Iinclude"
수 .#include "mylib/endian.h"
다른 라이브러리나 시스템 라이브러리와 충돌하지 않아야 합니다.
입니다.-I
위험한 건 거짓입니다 는 이 언어는 두 가지 형식 중 하나로 헤더 파일을 검색합니다 형식 중로 헤더 파일을 합니다.#include
표준 헤더 파일의 이름과 충돌하는 헤더 파일을 사용하는 것은 안전하지 않다는 것을 충분히 정의했습니다.그냥 이런 짓은 삼가세요.
명백한 경우는 교차 편집입니다.GCC는 항상 로컬 시스템용으로 컴파일하거나 최소한 매우 가까운 UNIX를 사용한다는 역사적인 가정으로 인해 어려움을 겪고 있습니다.이것이 컴파일러의 헤더 파일이 시스템 루트에 있는 이유입니다.깨끗한 인터페이스가 없습니다.
이에 비해 Windows는 컴파일러가 없다고 가정하고 Windows 컴파일러는 로컬 시스템을 대상으로 한다고 가정하지 않습니다.그렇기 때문에 컴파일러 세트와 SDK 세트를 설치할 수 있습니다.
이제 교차 컴파일에서 GCC는 Windows용 컴파일러와 훨씬 더 유사하게 동작합니다.더 이상 로컬 시스템 헤더를 사용할 것이라고 가정하지 않고 원하는 헤더를 정확하게 지정할 수 있습니다.그리고 분명히, 당신이 링크하는 도서관들도 마찬가지입니다.
이렇게 하면 교체 헤더 집합이 기본 시스템 위에 올라가도록 설계됩니다.동일한 구현일 경우 대체 집합에서 헤더를 생략할 수 있습니다.예를 들어 그럴 가능성이 있습니다.<complex.h>
마찬가지입니다.복잡한 숫자 구현에는 큰 차이가 없습니다.다와 는 없습니다.<endian.h>
.
TL,DR : 자신이 무엇을 하고 있는지 아는 사람들을 위한 경우 이 옵션."안전하지 못하다는 것"은 대상이 되는 청중을 위한 논쟁이 아닙니다.
언급URL : https://stackoverflow.com/questions/53154898/why-do-projects-use-the-i-include-switch-given-the-dangers
'programing' 카테고리의 다른 글
Android에서 활동에서 단편으로 데이터 전송 (0) | 2023.10.07 |
---|---|
git reset --hard HEAD~1'과 'git reset --soft HEAD~1'의 차이점은 무엇입니까? (0) | 2023.10.07 |
XML 문서에 HTML 내용을 삽입할 수 있습니까? (0) | 2023.10.07 |
팬더 데이터 프레임에 열 레벨을 간단히 추가하는 방법 (0) | 2023.10.07 |
크로스 브라우저 자바스크립트 XML 구문 분석 (0) | 2023.10.07 |