문제

편집 시간 (Linux/UNIX)을 매우 느리게하는 "헤더 스파게티"를 정리하기위한 권장되는 관행?

GCC에 "#pragma Once"와 동일한 기능이 있나요?
(이와 관련하여 상충되는 메시지를 발견했습니다)

감사해요.

도움이 되었습니까?

해결책

"포함 가드"(헤더 시작 부분의 #ifdef..)에 익숙하다고 가정하면, 빌드 시간을 단축하는 또 다른 방법은 외부 포함 가드를 사용하는 것입니다."에서 논의되었습니다.대규모 C++ 소프트웨어 설계".아이디어는 #pragma Once와 달리 클래식 포함 가드가 두 번째부터 헤더를 무시하는 데 필요한 전처리기 구문 분석을 아끼지 않는다는 것입니다(예:여전히 포함 가드의 시작과 끝을 구문 분석하고 찾아야 합니다.외부 포함 가드를 사용하면 #include 줄 자체 주위에 #ifdef를 배치합니다.

따라서 다음과 같습니다.

#ifndef MY_HEADER
#include "myheader.h"
#endif

물론 H 파일에는 클래식 포함 가드가 있습니다.

#ifndef MY_HEADER
#define MY_HEADER

// content of header

#endif

이렇게 하면 myheader.h 파일이 전처리기에 의해 열리거나 구문 분석되지도 않으며 대규모 프로젝트에서 많은 시간을 절약할 수 있습니다. 특히 헤더 파일이 공유 원격 위치에 있을 때 그렇습니다.

다시 말하지만, 그 책에 다 나와 있어요.h번째

다른 팁

완전한 정리를 수행하고 이를 수행할 시간이 있는 경우 가장 좋은 해결책은 모든 파일에서 모든 #include를 삭제하는 것입니다(예: 명백한 파일은 제외).abc.cpp의 abc.h)를 생성한 다음 프로젝트를 컴파일합니다.첫 번째 오류를 수정하는 데 필요한 전방 선언이나 헤더를 추가한 다음 완전히 완료될 때까지 반복합니다.

이는 포함 문제를 일으킬 수 있는 근본적인 문제를 해결하지는 않지만 유일한 포함이 필수 항목인지 확인합니다.

나는 GCC가 고려한다는 것을 읽었습니다. #pragma once 더 이상 사용되지 않지만 #pragma once 작업 속도를 높이기 위해 많은 일을 할 수 있습니다.

얽힌 것을 풀려고 노력하다 #include 스파게티, 너도 볼 수 있어 독산소.포함된 헤더의 그래프를 생성할 수 있어야 하며, 이는 작업을 단순화하는 데 유리할 수 있습니다.세부 사항을 직접 기억할 수는 없지만 그래프 기능을 사용하려면 설치가 필요할 수 있습니다. 그래프비즈 GraphViz의 dotty.exe를 찾을 수 있는 경로를 doxygen에 알려줍니다.

컴파일 시간이 주요 관심사인 경우 고려할 수 있는 또 다른 접근 방식은 다음을 설정하는 것입니다. 미리 컴파일된 헤더.

얼마전에 헤더 종속성을 줄이는 깔끔한 방법에 대해 읽었습니다.다음을 수행하는 스크립트를 작성하세요.

  • 모든 #include 문을 찾으세요
  • 한 번에 하나의 명령문을 제거하고 다시 컴파일
  • 컴파일이 실패하면 include 문을 다시 추가하세요.

결국에는 코드에 필요한 최소한의 포함이 이루어지기를 바랍니다.포함 내용을 다시 정렬하여 자체적으로 충분한지 확인하거나 다른 헤더가 그 앞에 포함되도록 요구하는 유사한 스크립트를 작성할 수 있습니다(헤더를 먼저 포함하고, 컴파일이 실패하는지 확인하고, 보고합니다).그러면 코드를 정리하는 데 도움이 될 것입니다.

추가 참고사항:

  • 최신 컴파일러(그 중 gcc)는 헤더 가드를 인식하고 pragma와 동일한 방식으로 최적화하여 파일을 한 번만 엽니다.
  • pragma Once는 동일한 파일이 파일 시스템에서 다른 이름을 가질 때 문제가 될 수 있습니다(예:소프트 링크 포함)

  • gcc는 #pragma를 한 번만 지원하지만 "구식"이라고 부릅니다.
  • pragma Once는 모든 컴파일러에서 지원되지 않으며 C 표준의 일부도 아닙니다.

  • 컴파일러만이 문제가 될 수 있는 것은 아닙니다.Incredibuild와 같은 도구에도 #pragma Once와 관련된 문제가 있습니다.

Richard의 말이 다소 옳았습니다(왜 그의 솔루션이 기록되었나요?).

어쨌든 모든 C/C++ 헤더는 내부 포함 가드를 사용해야 합니다.

이는 다음 중 하나를 의미합니다.

1 - 레거시 코드는 더 이상 유지 관리되지 않으며 미리 컴파일된 헤더를 사용해야 합니다(해킹이지만...유지 관리되지 않는 코드를 리팩터링하는 것이 아니라 컴파일 속도를 높이는 것이 필요합니다)

2 - 레거시 코드가 아직 살아 있습니다.그런 다음 임시 솔루션을 위해 사전 컴파일된 헤더 및/또는 가드/외부 가드를 사용하지만 결국에는 한 번에 하나씩 .C 또는 .CPP 하나씩 모든 포함을 제거하고 각 . C 또는 .CPP 파일을 한 번에 하나씩 수정하고 필요한 경우 전방 선언 또는 포함을 사용하여 포함을 수정합니다(또는 각 .C 또는 .CPP 파일이 필요한 헤더만 얻을 수 있도록 큰 포함을 작은 파일로 분할할 수도 있음).어쨌든, 오래된 포함을 테스트하고 제거하는 것은 프로젝트 유지 관리의 일부이므로...

미리 컴파일된 헤더에 대한 내 경험은 그다지 좋지 않았습니다. 절반의 시간 동안 컴파일러는 내가 정의한 기호를 찾을 수 없었기 때문에 전체 "정리/재구축"을 시도하여 미리 컴파일된 헤더가 아닌지 확인했습니다. 그것은 쓸모가 없었습니다.그래서 내 생각에는 STL, C API 헤더, Boost 등과 같이 만지지도 않을 외부 라이브러리에 이를 사용하는 것입니다.그래도 내 경험은 Visual C++ 6에서 이루어졌으므로 지금은 제대로 작동했을 것 같습니다(희망?).

이제 마지막으로 한 가지:헤더는 항상 자급자족해야 합니다.즉, 헤더 포함이 포함 순서에 따라 달라지면 문제가 있는 것입니다.예를 들어, 다음과 같이 쓸 수 있다면:

#include "AAA.hpp"
#include "BBB.hpp"

하지만:

#include "BBB.hpp"
#include "AAA.hpp"

BBB는 AAA에 의존하기 때문에 당신이 가진 것은 코드에서 결코 인정하지 않은 의존성뿐입니다.정의로 이를 승인하지 않으면 컴파일이 악몽으로 변할 뿐입니다.BBB에는 AAA도 포함되어야 합니다(다소 속도가 느리더라도:결국 전방 선언은 쓸모없는 포함을 정리하므로 컴파일 타이머가 더 빨라야 합니다.

빌드 시간을 단축하려면 그 중 하나 이상을 사용하십시오.

  1. 미리 컴파일된 헤더 사용
  2. 캐싱 메커니즘 사용(예: scons)
  3. 분산 빌드 시스템 사용( distcc, Incredibuild($) )

헤더에서:전방 선언을 사용할 수 없는 경우에만 헤더를 포함하되, 필요한 모든 파일을 항상 #include합니다(종속성 포함은 사악합니다!).

다른 답변에서 언급했듯이 가능하면 반드시 전방 선언을 사용해야 합니다.내가 아는 바로는 GCC에는 #pragma Once와 동등한 것이 없기 때문에 나는 인클루드 가드라는 구식 패션 스타일을 고수합니다.

답장을 보내주셔서 감사합니다. 하지만 문제는 엄격한 "포함 순서" 등을 포함하는 기존 코드에 관한 것입니다.문제는 실제로 무슨 일이 일어나고 있는지 명확히 하기 위한 도구/스크립트가 있는지 여부입니다.

헤더 가드는 컴파일러가 전체 파일을 계속해서 읽는 것을 방해하지 않기 때문에 해결책이 아닙니다.

PC-Lint 스파게티 헤더를 청소하는 데 큰 도움이 될 것입니다.또한 초기화되지 않은 변수가 보이지 않는 등의 다른 문제도 해결해 줍니다.

onebyone.livejournal.com이 귀하의 질문에 대한 응답으로 언급했듯이 일부 컴파일러는 다음을 지원합니다. 가드 최적화 포함, 내가 링크한 페이지는 다음과 같이 정의합니다.

포함 가드 최적화는 컴파일러가 위에서 설명한 내부 포함 가드 관용구를 인식하고 파일을 여러 번 열지 않도록 조치를 취하는 경우입니다.컴파일러는 포함 파일을 보고, 주석과 공백을 제거하고, 파일 전체가 포함 가드 내에 있는지 알아낼 수 있습니다.그렇다면 파일 이름을 저장하고 가드 조건을 맵에 포함합니다.다음에 컴파일러가 파일을 포함하도록 요청하면 포함 가드 조건을 확인하고 파일을 열 필요 없이 파일을 건너뛸지 아니면 #include할지 결정할 수 있습니다.

그런 다음 외부 포함 가드는 귀하의 질문에 대한 답변이 아니라고 이미 답변하셨습니다.특정 순서로 포함되어야 하는 헤더 파일을 풀려면 다음을 제안합니다.

  • .c 또는 .cpp 파일은 #include 해당 .h 파일을 먼저 제출하고 나머지는 #include 지시문은 알파벳순으로 정렬되어야 합니다.헤더 파일 간의 명시되지 않은 종속성이 깨지면 일반적으로 빌드 오류가 발생합니다.
  • 기본 유형 또는 전역에 대한 전역 형식 정의를 정의하는 헤더 파일이 있는 경우 #define 대부분의 코드에 사용되는 지시어 .h 파일은 #include 해당 파일을 먼저, 나머지는 #include 지시문은 알파벳순으로 정렬되어야 합니다.
  • 이러한 변경으로 인해 컴파일 오류가 발생하는 경우 일반적으로 다음과 같은 형식으로 한 헤더 파일에서 다른 헤더 파일로 명시적인 종속성을 추가해야 합니다. #include.
  • 이러한 변경으로 인해 컴파일 오류가 발생하지 않으면 동작이 변경될 수 있습니다.애플리케이션의 기능을 확인하는 데 사용할 수 있는 일종의 테스트 도구 모음이 있기를 바랍니다.

또한 증분 빌드가 예상보다 훨씬 느린 것이 문제의 일부인 것처럼 들립니다.이 상황은 다른 사람들이 지적한 것처럼 전방 선언이나 분산 빌드 시스템을 통해 개선될 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top