C / C ++에서 불필요한 #include를 감지합니까?


289

종종 파일의 헤더 섹션이 항상 커지고 커지지 만 결코 작아지지는 않습니다. 소스 파일의 수명 동안 클래스는 이동하고 리팩토링되었을 #includes수 있으며, 더 이상 필요하지 않은 클래스가있을 가능성이 매우 높습니다 . 그것들을 그대로두면 컴파일 시간이 길어지고 불필요한 컴파일 종속성이 추가됩니다. 여전히 필요한 것이 무엇인지 파악하는 것은 매우 지루할 수 있습니다.

불필요한 #include 지시문을 감지하고 안전하게 제거 할 수있는 명령을 제안 할 수있는 도구가 있습니까?
보풀이이 작업을 수행합니까?



1
연결된 질문은 특히 Visual Studio를 사용하여 Windows의 문제를 해결하는 것 같습니다.
D' Nabre

7
복제본이 특히 Visual Studio 사용에 관한 것이므로 이것을 다시 열기로 투표합니다.
Drew Dormann

답변:


42

자동은 아니지만 doxygen#included파일에 대한 종속성 다이어그램을 생성 합니다. 시각적으로 살펴 봐야하지만 무엇을 사용하고 있는지에 대한 그림을 얻는 데 매우 유용 할 수 있습니다.


5
이것은 체인을 보는 좋은 방법입니다. A-> B-> C-> D 및 A-> D를 보면 즉시 중복성이 드러납니다.
Tom

34
@Tom : 그것은 끔찍한 아이디어입니다. 하나는 포함이 필요하거나 그렇지 않은지를 보여주지 않습니다. 포함 목록은 미래에 변경 될 수있는 간접 포함에 의존해서는 안됩니다 (중복 포함은 일반적으로 그렇지 않습니다) 가드와 컴파일러 마술을 포함하여 큰 문제가 있지만 파일에서 실제로 어떤 클래스 / 함수가 사용되는지 (컴파일러는 인스턴스화되지 않는 수천 줄의 템플릿 코드를 거치지 않아도됩니다)
MikeMB

@albert, 이것의 스크린 샷을 포함하고 doxygen 출력에서 ​​클릭 위치를 간단히 설명 할 수 있습니까?
Gabriel Staples

@GabrielStaples 내 대답이 아니므로 정보를 추가하고 싶지 않습니다. 링크 만 수정했습니다 (호스팅 장소가 중지 / 사용 된 것으로 간주 됨).
앨버트

177

Google의 cppclean (links : download , documentation )은 여러 범주의 C ++ 문제를 찾을 수 있으며 이제 불필요한 #include를 찾을 수 있습니다.

Clang 기반 도구 인 include-what-you-use 도 있습니다. include-what-you-use는 포워드 선언을 제안하고 (따라서 #include하지 않아도 됨) 선택적으로 #include를 정리합니다.

현재 버전의 Eclipse CDT 에는이 기능이 내장되어 있습니다. 소스 메뉴에서 포함 구성을 클릭하면 #include를 알파벳순으로 표시하고 Eclipse가 직접 포함하지 않고 사용한다고 생각하는 헤더를 추가하고 포함하지 않은 헤더는 주석 처리합니다 당신이 필요하다고 생각하지 않습니다. 그러나이 기능은 100 % 신뢰할 수 없습니다.


2
지금은 그렇습니다. 나는 그것을 사용하기 시작했다. 여기 내 메모를 참조하십시오. stackoverflow.com/questions/1301850/…
Chance

1
cppclean 리포지토리가 다운되었으므로 이제 여기를 얻을 수 있습니다. bitbucket.org/robertmassaioli/cppclean (원래 사이트는 일부 예제 사용에 여전히 유용합니다)
Nick

3
유지 된 cppclean 포크에 대한 링크를 업데이트했습니다 : github.com/myint/cppclean
BenC

1
cppclean은 문서의 "불필요한 #includes in header files"문서에서 cpp 파일이 아닌 헤더 파일에서만 찾을 수 있습니다.
Zitrax

1
@wizurd-Eclipse CDT의 최근 개발 내용을 따르지 않았지만 그렇게 생각하지 않습니다. iwyu는 철저하고 상대적으로 느립니다. Eclipse CDT의 분석은 빠르며 (대화식), 테스트 할 때 정확도가 떨어집니다.
조쉬 켈리

65

또한 include-what-you-use 를 확인하여 비슷한 문제를 해결하십시오.


6
IMHO이 답변은 일단 꼬임이 해결되면 Google의 IWYU 도구가이 작업을위한 결정적인 도구가되기 때문에 더 많은지지가 필요합니다.
Dan Olson

5
sudo apt-get install iwyu
Andrew Wagner

1) 마지막 업데이트 2 월 2106 2) Gogole은 OP가 요청한 C가 아닌 C ++에만 사용합니다.
Mawg는 모니카

사용자가 어떻게 사용해야하는지 조금 설명해 주시겠습니까? README는 파이썬 스크립트의 출력을 포함하는 내용에 대해 명확하지 않습니다.
King 's jester

나는 이것을 사용하고 있지만 항상 100 % 정확하지는 않습니다. 아마도 70 % 배가 올바른 제안을합니다.
InQusitive

25

불필요한 포함을 감지하는 데있어 문제점은 유형 종속성 검사기가 될 수 없다는 것입니다. 포함 불필요한이 편집에 가치의 아무것도 제공하지 않는 파일 다른 파일이 의존하는 다른 항목을 변경하지 않습니다. 헤더 파일이 컴파일을 변경하는 방법에는 여러 가지가 있습니다. 예를 들어, 상수를 정의하고, 사용 된 매크로를 재정의 및 / 또는 삭제하고, 네임 스페이스를 추가하여 이름의 조회를 줄 아래로 변경하는 등의 방법이 있습니다. 네임 스페이스와 같은 항목을 탐지하려면 전 처리기보다 훨씬 더 많은 것이 필요하므로 실제로는 완전한 컴파일러가 거의 필요합니다.

Lint는 더 많은 스타일 검사기이며이 기능을 완전히 갖추고 있지는 않습니다.

불필요한 포함을 감지하는 유일한 방법은 제품군을 제거, 컴파일 및 실행하는 것입니다.


8
포함 파일이 제대로 배치되어 있으면이 중 어느 것도 문제가되지 않습니다. 파일 B 앞에 파일 A를 포함 해야하는 경우 잘못하고 있습니다 (그리고 그들이 잘못한 프로젝트에서 작업했습니다).
David Thornley 2014 년

9
@David, 그렇습니다.하지만 제대로하기 전에 수년간의 개발자에 달려 있습니다. 나는 그 일이 일어날 가능성이 당신이 아니라 집을 선호한다고 확신 할 수있다. (
JaredPar

예, 그러나 일반적으로 프로그램을 수정할 때 그 사실을 알게되고 갑자기 컴파일 오류 (운이 좋으면) 또는 모호한 버그가 발생합니다. 적어도 장기적으로는 #include 파일을 정직하게 유지하는 것 같습니다.
David Thornley

나는 정확히 반대라고 말하고 싶습니다. 필요한 것은 타입 의존성 검사기입니다. 포함을 적절하게 배열 한 후에는 컴파일되지 않을 수도 있지만, 어쨌든 다루어야 할 문제입니다.
Benoît

1
@Benoit, 그렇다면 프로그램의 의미를 컴파일하지만 의미 적으로 변경하는 일련의 문제는 무시할 것입니다. 한 파일의 #define이 다른 파일의 #if 분기를 어떻게 변경할 수 있는지 고려하십시오. 헤더를 제거하면 여전히 다른 결과를 컴파일 할 수 있습니다
JaredPar

15

나는 PCLint이것을 할 것이라고 생각 했지만, 그것을 본 지 몇 년이 지났다 . 당신은 그것을 확인할 수 있습니다.

나는 쳐다 보면서 이 블로그 와 저자가 사용되지 않는 포함 찾을 PCLint 구성에 대한 조금 이야기했다. 살펴볼 가치가 있습니다.


잘 찾아라! 나는 그것을 사용해야 할 것이다.
crashmstr

4
PCLint를 정기적으로 사용하며 사용하지 않는 헤더에 대해 알려줍니다. 헤더 #include를 주석 처리하고 다시 컴파일하여 헤더가 실제로 사용되지 않는지 확인하십시오 ...
Harold Bamford

확인 주셔서 감사합니다, 해롤드
itsmatt

5
너무 비싼. 대중을위한 실용적인 도구가 아닙니다.


5

단일 #include 지시문을 지우고 프로젝트를 컴파일하고 컴파일 오류가 발생하지 않은 경우 제거 된 파일과 #include에 이름을 기록하는 빠른 스크립트를 작성할 수 있습니다.

밤 중에 실행되도록하고 다음 날에는 제거 할 수있는 포함 파일의 100 % 올바른 목록이 표시됩니다.

때로는 무차별 강제 작동 :-)


편집 : 때로는 그렇지 않습니다 :-). 주석의 정보는 다음과 같습니다.

  1. 때로는 두 개의 헤더 파일을 개별적으로 제거 할 수 있지만 둘 다 제거 할 수는 없습니다. 해결책은 실행 중에 헤더 파일을 제거하고 다시 가져 오지 않는 것입니다. 이 알고리즘으로 찾을 수없는 파일이 더 많은 솔루션이있을 수 있지만 안전하게 제거 할 수있는 파일 목록을 찾을 수 있습니다. (제거 할 포함 파일 공간에 대한 욕심 많은 검색입니다. 로컬 최대 값 만 찾습니다)
  2. 일부 #ifdef에 따라 일부 매크로가 다르게 재정의되면 동작에 미묘한 변화가있을 수 있습니다. 나는 이것이 매우 드문 경우라고 생각하며 빌드의 일부인 단위 테스트는 이러한 변화를 포착해야합니다.

1
이것을 조심하십시오-두 개의 헤더 파일이 있으며 둘 다 무언가의 정의를 포함합니다. 둘 중 하나만 제거 할 수 있습니다. 무차별 대입 방식에는 좀 더 철저해야합니다.
Dominic Rodger 2016 년

어쩌면 이것이 의미하는 것이지만, 단일 포함을 제거하고 성공적으로 제거 된 마지막 제거 포함을 남겨 두는 스크립트는 트릭을 수행합니다.
Dominic Rodger 2016 년

1
나쁜 생각. 헤더 파일 #가 상수 BLAH를 정의하고 다른 헤더 파일이 #ifdef BLAH를 검사하는 경우 첫 번째 헤더 파일을 제거해도 여전히 컴파일이 가능하지만 동작이 변경되었습니다.
Graeme Perrow 2014 년

1
구현마다 #include <vector>에 포함 된 항목이 다르기 때문에 시스템 헤더에 문제가 발생할 수도 있습니다. 하나의 컴파일러를 고수하더라도 헤더는 다른 버전으로 변경 될 수 있습니다.
David Thornley 2014 년

2
실제로 필요한 헤더가 포함 된 헤더를 포함하는 경우는 찾을 수 없습니다.
bk1e

5

여기에 (다시) 게시하여 죄송합니다. 사람들은 종종 댓글을 확장하지 않습니다.

crashmstr에 대한 내 의견을 확인하십시오. FlexeLint / PC-Lint 가이 작업을 수행합니다. 정보 메시지 766. 내 설명서 (버전 8.0)의 11.8.1 절에서 이에 대해 설명합니다.

또한 이것은 중요하며 메시지가 사라질 때까지 반복하십시오 . 즉, 사용하지 않는 헤더를 제거한 후 보푸라기를 다시 실행하면 불필요한 헤더를 제거하면 더 많은 헤더 파일이 "필요하지 않은"것일 수 있습니다. (이것은 어리석은 소리, 천천히 읽고 해석하는 것이 합리적입니다.)


당신이 무슨 뜻인지 정확히 알고 제 반응은 "Ewwww"였습니다. 나는 그런 코드가 싫어.
David Thornley

5

나는 당신이 요구하는 것을 성취하는 본격적인 도구를 찾지 못했습니다. 내가 사용한 가장 가까운 것은 IncludeManager입니다 . 헤더 포함 트리를 그래프로 표시하여 하나의 파일에 포함 된 헤더와 원형 헤더 포함을 시각적으로 볼 수 있습니다.


4

Flexelint (Unix 버전의 PC-Lint)를 사용해 보았지만 결과가 약간 다릅니다. 이것은 매우 크고 코드가 많은 코드 기반으로 작업하고 있기 때문일 수 있습니다. 사용하지 않은 것으로보고 된 각 파일을주의 깊게 검사하는 것이 좋습니다.

가장 큰 걱정은 오 탐지입니다. 동일한 헤더의 여러 포함이 불필요한 헤더로보고됩니다. Flexelint가 헤더가 포함 된 행 또는 이전에 포함 된 행을 알려주지 않기 때문에 이것은 나쁩니다.

자동화 된 도구가이를 잘못 해결할 수있는 방법 중 하나 :

A.hpp에서 :

class A { 
  // ...
};

B.hpp에서 :

#include "A.hpp

class B {
    public:
        A foo;
};

C.cpp에서 :

#include "C.hpp"  

#include "B.hpp"  // <-- Unneeded, but lint reports it as needed
#include "A.hpp"  // <-- Needed, but lint reports it as unneeded

Flexelint의 메시지를 맹목적으로 따르는 경우 #include 종속성이 막힙니다. 더 많은 병리학 적 사례가 있지만 기본적으로 최상의 결과를 얻으려면 헤더를 직접 검사해야합니다.

게임 내 블로그에서 실제 구조 및 C ++ 에 대한이 기사를 적극 권장합니다 . #include 혼란을 정리하기위한 포괄적 인 접근 방식을 권장합니다.

지침

다음은 파일 간의 물리적 종속성 수를 최소화하는 Lakos의 책에서 나온 일련의 지침입니다. 나는 수년 동안 그것들을 사용해 왔으며 항상 결과에 정말 만족했습니다.

  1. 모든 cpp 파일은 먼저 자체 헤더 파일을 포함합니다. [한조각]
  2. 헤더 파일에는 구문 분석에 필요한 모든 헤더 파일이 포함되어야합니다. [한조각]
  3. 헤더 파일에는 구문 분석에 필요한 최소한의 헤더 파일 수가 있어야합니다. [한조각]

Lakos의 책은 컴파일러 기술에 대한 그의 오래된 관찰과는 별도로 교육에 적합합니다.
Tom

4

Eclipse CDT를 사용하는 경우 http://includator.com 을 사용하여 베타 테스터에게 무료로 제공 할 수 있으며 (이 글을 쓰는 시점에) 무료 #include를 포함하거나 누락 된 것을 자동으로 제거합니다. FlexeLint 또는 PC-Lint를 사용하고 Elicpse CDT를 사용하는 사용자의 경우 http://linticator.com 이 옵션 일 수 있습니다 (베타 테스트는 무료). Lint의 분석을 사용하지만 불필요한 #include 문을 자동으로 제거하기위한 빠른 수정 사항을 제공합니다.


그 이유는 부기 부서에서 더 적은 금액을 청구 할 수 없기 때문입니다. 당신이 시간을 계산하면 시간을 절약하는 것은 무리가 아닙니다. 신용 카드 결제가 가능 해지면 가격을 크게 낮출 수 있습니다. 또 다른 옵션은 우리의 개발 노력을위한 후원자 일 것입니다. 우리의 자금 조달 모델은 연구 업무에 자금을 조달하기 위해 이익을 얻도록 요구합니다. 라이센스를 훨씬 저렴하게 판매 할 수는 있지만 할 수는 없습니다. CDT에 기부하면 무료로받을 수 있지만 어떻게 든 자금을 조달해야합니다. 잊어 버렸습니다, 당신은 무료로 시도 할 수 있습니다!
PeterSom

2

이 기사에서는 Doxygen의 구문 분석을 사용하여 #include 제거 기술에 대해 설명합니다. 펄 스크립트 일 뿐이므로 사용하기가 매우 쉽습니다.


1
스크립트는 제거 할 일부 포함을 찾았지만 제거 할 수없는 많은 포함도 제공합니다. 클래스 열거 형을 지원하지 않는 것 같습니다. 매크로와 때로는 네임 스페이스가 좋지 않은 것 같습니다.
Baptiste Wicht



1

불필요한 #include 파일에는 두 가지 유형이 있습니다.

  1. 실제로 모듈 (.c, .cpp)에 필요하지 않은 헤더 파일
  2. 헤더 파일은 모듈에 필요하지만 두 번 이상, 직접 또는 간접적으로 포함됩니다.

내 경험에는 그것을 감지하는 데 잘 작동하는 두 가지 방법이 있습니다.

  • gcc -H 또는 cl.exe / showincludes (문제 2 해결)

    실제로는 모든 Makefile이 CFLAGS 옵션을 무시하지 않는 경우 만들기 전에 CFLAGS = -H를 내보낼 수 있습니다. 또는 내가 사용한 것처럼 cc / g ++ 래퍼를 만들어 $ (CC) 및 $ (CXX)를 호출 할 때마다 -H 옵션을 강제로 추가 할 수 있습니다. 래퍼의 디렉토리를 $ PATH 변수 앞에 추가하면 make가 대신 래퍼 명령을 대신 사용합니다. 물론 래퍼는 실제 gcc 컴파일러를 호출해야합니다. Makefile이 gcc를 직접 사용하는 경우이 트릭을 변경해야합니다. $ (CC) 또는 $ (CXX) 대신 또는 묵시적 규칙.

    명령 행을 조정하여 단일 파일을 컴파일 할 수도 있습니다. 그러나 전체 프로젝트의 헤더를 정리하려면 다음을 통해 모든 출력을 캡처 할 수 있습니다.

    깨끗하게하다

    2> & 1 | 티 result.txt

  • PC-Lint / FlexeLint (1과 2의 문제 해결)

    + e766 옵션을 추가하십시오.이 경고는 사용되지 않은 헤더 파일입니다.

    pclint / 플린트 -vf ...

    이로 인해 pclint 출력에 헤더 파일이 포함되고 중첩 된 헤더 파일이 적절히 들여 쓰기됩니다.


1

이 논의를 끝내기 위해 : c ++ 전처리 기가 완전히 작동합니다. 포함이 불필요한 지 여부는 의미 적 특성입니다. 따라서 쌀의 정리에 따르면 포함이 불필요한 지 여부를 결정할 수 없습니다. 포함이 불필요한 지 여부를 항상 감지하는 프로그램은있을 수 없습니다.


5
"항상 올바른"솔루션을 요청 했습니까? 이 답변은 토론에 매우 생산적이지 않습니다.
shoosh

1
그러한 프로그램이 다루어야 할 문제에 대해 많은 게시물이 있습니다. 내 게시물은 토론의 해당 부분에 대한 결정적이고 정확한 답변을 제공합니다. 그리고 나는 그것을 좋아하지 않을 것입니다. 프로그램이 말해 주면 #include를 안전하게 제거 할 수 있으며 코드가 더 이상 컴파일되지 않습니다. (또는 악화-여전히 컴파일되지만 다르게 작동합니다). 그러한 프로그램은이 위험을 감수합니다.
Algoman

4
그것이 얼마나 어려울 지, 어떻게 장애물을 해결할 수 있는지에 대한 모든 사양 사이에서, 나는 당신에게 유일한 100 % 정답을 주었다. 나는 이것이 생산적이지 않다고 말하는 것이
무례하다는 것을 안다

1
라이스의 정리는 "주어진 프로그램이이 불필요한 포함 문제를 해결할 수 있는지 항상 확인할 수있는 프로그램은 없다"는 것을 기억했다. 불필요한 포함 문제를 해결하는 몇 가지 프로그램이있을 수 있습니다.
Zhe Yang

1
개인적으로 @Algoman의 입력이 매우 유용하다는 것을 알았습니다. 이 문제가 얼마나 어려운지 깨달았습니다.
bogardon


0

Gimpel Software의 PC Lint 는 포함 파일이 컴파일 장치에 두 번 이상 포함 된 경우보고 할 수 있지만 원하는 방식으로 필요하지 않은 포함 파일을 찾을 수 없습니다.

편집 : 가능합니다. 참조 itsmatt의 답변을


당신은 확실히 그것에 대해? C ++ 코드에서 FlexeLint (PCL과 동일)를 몇 년 동안 사용하지 않았지만 최근에는 C 코드에서도 사용되지 않은 헤더 파일에 대해 몇 가지 메시지 (코드 766이라고 생각합니다)를 보았습니다. 방금 확인 (v8.0), 섹션 11.8.1 참조 수동.
Dan

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.