Jak wykryć niepotrzebne pliki # include w dużym projekcie C++?

Pracuję nad dużym projektem C++ w Visual Studio 2008 i jest tam dużo plików ze zbędnymi dyrektywami #include. Czasami #include S są tylko artefaktami i wszystko będzie się dobrze skompilować po ich usunięciu, a w innych przypadkach klasy mogą być zadeklarowane i # include mogą być przeniesione do pliku .cpp. Czy są jakieś dobre narzędzia do wykrywania obu tych przypadków?

Author: LogicStuff, 2008-09-16

20 answers

Chociaż nie wyświetla niepotrzebnych plików nagłówkowych, Visual studio ma ustawienie /showIncludes (kliknij prawym przyciskiem myszy na pliku .cpp, Properties->C/C++->Advanced), które wyświetli drzewo wszystkich dołączonych plików podczas kompilacji. Może to pomóc w identyfikacji plików, które nie powinny być dołączane.

Możesz również spojrzeć na idiom pimpl, aby uniknąć mniej zależności od plików nagłówkowych, aby ułatwić zobaczenie cruft, który możesz usunąć.

 45
Author: Eclipse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-22 22:49:10

PC Lint działa całkiem dobrze na to, i znajduje wiele innych głupich problemów również dla Ciebie. Posiada opcje wiersza poleceń, które można wykorzystać do tworzenia zewnętrznych narzędzi w Visual Studio, ale odkryłem, że dodatek Visual Lint jest łatwiejszy w obsłudze. Pomaga nawet darmowa wersja Visual Lint. Ale daj szansę PC-Lintowi. Skonfigurowanie go tak, aby nie dawał zbyt wielu ostrzeżeń zajmuje trochę czasu, ale będziesz zaskoczony tym, co się pojawia.

 28
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 17:34:20

Jest nowe narzędzie oparte na Clang, include-what-you-use , które ma na celu to zrobić.

 26
Author: Josh Kelley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-05 14:56:32

!!DISCLAIMER!! Pracuję na komercyjnym narzędziu do analizy statycznej (Nie PC Lint). !!DISCLAIMER!!

Istnieje kilka problemów z prostym Nie parsującym podejściem:

1) Zestawy Przeciążeniowe:

Jest możliwe, że przeciążona funkcja ma deklaracje pochodzące z różnych plików. Może się zdarzyć, że usunięcie jednego pliku nagłówkowego spowoduje wybranie innego przeciążenia, a nie błąd kompilacji! Rezultatem będzie cicha zmiana semantyki, która może być bardzo trudna do namierz później.

2) specjalizacje szablonów:

Podobnie jak w przykładzie przeciążenia, jeśli masz częściowe lub jawne Specjalizacje dla szablonu, chcesz, aby wszystkie były widoczne podczas używania szablonu. Możliwe, że Specjalizacje dla szablonu podstawowego znajdują się w różnych plikach nagłówkowych. Usunięcie nagłówka ze specjalizacją nie spowoduje błędu kompilacji, ale może spowodować nieokreślone zachowanie, jeśli ta specjalizacja zostałaby wybrana. (Patrz: widoczność specjalizacji szablonu funkcji C++ )

Jak zauważył "msalters", przeprowadzenie pełnej analizy kodu pozwala również na analizę użycia klasy. Sprawdzając, w jaki sposób klasa jest używana przez określoną ścieżkę plików, możliwe jest, że definicja klasy (a więc wszystkie jej zależne) może zostać całkowicie usunięta lub przynajmniej przeniesiona na poziom bliżej głównego źródła w drzewie include.

 25
Author: Richard Corden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:04

Nie znam żadnych takich narzędzi i myślałem o napisaniu jednego w przeszłości, ale okazuje się, że jest to trudny problem do rozwiązania.

Powiedzmy, że Twój plik źródłowy zawiera a. h I b. h; A. H zawiera #define USE_FEATURE_X, A b. H używa #ifdef USE_FEATURE_X. Jeśli #include "a.h" jest skomentowany, Twój plik może się skompilować, ale może nie wykonać tego, czego oczekujesz. Wykrywanie tego programowo {[10] } jest nietrywialne.

Jakiekolwiek narzędzie to zrobi, musi znać również twoje środowisko kompilacji. Jeśli A. h wygląda like:

#if defined( WINNT )
   #define USE_FEATURE_X
#endif

Wtedy USE_FEATURE_X jest zdefiniowane tylko wtedy, gdy WINNT jest zdefiniowane, więc narzędzie musi wiedzieć, jakie dyrektywy są generowane przez sam kompilator, a które są określone w poleceniu compile, a nie w pliku nagłówkowym.

 10
Author: Graeme Perrow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 17:00:00

Podobnie jak Timmermans, nie znam żadnych narzędzi do tego. Ale znam programistów, którzy napisali skrypt Perla (lub Pythona), aby spróbować skomentować każdą linię include po kolei, a następnie skompilować każdy plik.


Wygląda na to, że teraz Eric Raymond ma do tego narzędzie .

Google 's cpplint.py ma zasadę" include what you use "(wśród wielu innych), ale o ile mogę powiedzieć, nie " include tylko to, czego używasz."Nawet jeśli, to może być przydatne.

 9
Author: Max Lybbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-13 20:09:08

Jeśli jesteś zainteresowany tym tematem w ogóle, możesz sprawdzić Lakos ' Large Scale C++ Software Design . Jest to trochę przestarzałe, ale dotyczy wielu problemów "fizycznego projektowania", takich jak znalezienie absolutnego minimum nagłówków, które należy uwzględnić. Nie widziałem, żeby coś takiego omawiano nigdzie indziej.

 5
Author: Adrian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-07 21:19:03

Jeśli pliki nagłówkowe zazwyczaj zaczynają się od

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#endif

(w przeciwieństwie do używania #pragma raz) można by to zmienić na:

#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#else 
#pragma message("Someheader.h superfluously included")
#endif

A ponieważ kompilator wypisuje nazwę kompilowanego pliku cpp, to poinformuje cię co najmniej, który plik cpp powoduje wielokrotne wprowadzanie nagłówka.

 4
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 00:40:49

Wypróbuj Include Manager . Łatwo integruje się z Visual Studio i wizualizuje ścieżki dołączania, co pomaga znaleźć niepotrzebne rzeczy. Wewnętrznie używa Graphviz, ale jest o wiele więcej fajnych funkcji. I chociaż jest to produkt komercyjny, ma bardzo niską cenę.

 4
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-01 11:48:35

Możesz zbudować wykres include używając C/C++ Include File Dependencies Watcher i wizualnie znaleźć niepotrzebne include.

 4
Author: Vladimir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-30 08:32:26

PC-Lint rzeczywiście może to zrobić. Jednym z łatwych sposobów na to jest skonfigurowanie go tak, aby wykrywał tylko nieużywane pliki nagłówkowe i ignorował wszystkie inne problemy. Jest to dość proste - aby włączyć tylko wiadomość 766 ("plik nagłówka nie używany w module"), wystarczy podać opcje-W0 +e766 w wierszu poleceń.

To samo podejście może być również używane z powiązanymi komunikatami, takimi jak 964 ("plik nagłówka nie używany bezpośrednio w module") i 966 ("pośrednio dołączony plik nagłówka nie używany w module").

FWIW Pisałem o tym bardziej szczegółowo w blogu w zeszłym tygodniu w http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 20:42:30

Jeśli chcesz usunąć niepotrzebne pliki #include w celu skrócenia czasu kompilacji, twój czas i pieniądze mogą być lepiej wydane na równoległe tworzenie procesu za pomocą cl.exe / MP, make-j, Xoreax IncrediBuild , distcc / icecream , itp.

OczywiĹ "cie, jeĹ" li masz juĹź răłwnolegĺ 'y proces budowania i wciÄ ... Ĺź starasz siÄ ™ go przyspieszyć, wyczyĺ" Ä ‡ swoje dyrektywy #include i usunÄ ... Ä ‡ te niepotrzebne zaleĹźnoĹ " ci.

 2
Author: bk1e,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 06:02:15

Zacznij od KAŻDEGO pliku nagłówkowego i upewnij się, że każdy plik nagłówkowy zawiera tylko to, co jest konieczne do kompilacji. Wszelkie pliki nagłówka, które są następnie brakuje dla plików C++, można dodać do samych plików C++.

Dla każdego pliku include i źródłowego, komentuj każdy plik include pojedynczo i sprawdź, czy jest kompilowany.

Dobrym pomysłem jest również sortowanie plików nagłówkowych Alfabetycznie, a jeśli nie jest to możliwe, dodaj komentarz.

 2
Author: selwyn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 16:55:16

Dodanie jednej lub obu poniższych definicji # wykluczy często niepotrzebne pliki nagłówkowe i może znacznie poprawić czas kompilacji, zwłaszcza jeśli kod nie korzysta z funkcji Windows API.

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

Zobacz http://support.microsoft.com/kb/166474

 1
Author: Roger Nelson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 04:28:17

Jeśli jeszcze tego nie zrobiłeś, użycie wstępnie skompilowanego nagłówka, aby uwzględnić wszystko, czego nie zmienisz (nagłówki platformy, zewnętrzne nagłówki SDK lub statyczne już ukończone fragmenty projektu) będzie miało ogromne znaczenie w czasie kompilacji.

Http://msdn.microsoft.com/en-us/library/szfdksca (VS. 71). aspx

Również, chociaż może być za późno dla Twojego projektu, porządkowanie projektu w sekcje i nie grupowanie wszystkich lokalnych nagłówków do jednego dużego nagłówka głównego jest dobre ćwiczyć, choć wymaga to trochę dodatkowej pracy.

 1
Author: anon6439,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 11:12:51

Jeśli chcesz pracować z Eclipse CDT możesz wypróbować http://includator.com aby zoptymalizować strukturę include. Jednak Includator może nie wiedzieć wystarczająco dużo o predefiniowanych includerach VC++i skonfigurowanie CDT do używania VC++ z poprawnymi includerami nie jest jeszcze wbudowane w CDT.

 1
Author: PeterSom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-01 12:44:43

Najnowszy JetBrains IDE, CLion, automatycznie pokazuje (w kolorze szarym) elementy, które nie są używane w bieżącym pliku.

Możliwe jest również posiadanie listy wszystkich nieużywanych includes (a także funkcji, metod, itp...) z IDE.

 1
Author: Jean-Michaël Celerier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-26 21:08:59

Niektóre z istniejących odpowiedzi mówią, że to trudne. To prawda, ponieważ potrzebujesz pełnego kompilatora, aby wykryć przypadki, w których odpowiednia byłaby deklaracja forward. Nie można analizować C++ nie wiedząc, co oznaczają symbole; gramatyka jest po prostu zbyt niejednoznaczna. Musisz wiedzieć, czy dana nazwa nazywa klasę (może być zadeklarowana do przodu) czy zmienną (nie może). Ponadto, musisz być świadomy przestrzeni nazw.

 0
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-17 09:17:39

Może trochę za późno, ale kiedyś znalazłem skrypt WebKit perl, który zrobił to, co chciałeś. Będzie potrzebował trochę adaptacji, jak sądzę (nie znam się dobrze na perlu), ale powinno zadziałać:

Http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes

(jest to stara gałąź, ponieważ trunk nie ma już pliku)

 0
Author: rubenvb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-30 14:47:08

Jeśli istnieje konkretny nagłówek, który Twoim zdaniem nie jest już potrzebny (powiedzmy sznurek.h), możesz skomentować, że obejmują następnie umieścić to poniżej wszystkich zawiera:

#ifdef _STRING_H_
#  error string.h is included indirectly
#endif

Oczywiście nagłówki interfejsu mogą używać innej konwencji # define aby nagrać ich włączenie do pamięci CPP. Lub żadnej konwencji, w takim przypadku takie podejście nie zadziała.

Następnie odbudować. Istnieją trzy możliwości:

  • Buduje ok. sznurek.h nie był krytyczny dla kompilacji, a dołączenie za to można go usunąć.

  • # error trips. sznurek.g było zawarte pośrednio jakoś Nadal nie wiesz, czy string.h jest wymagane. Jeśli jest to wymagane, możesz powinien zawierać bezpośrednio #( patrz niżej).

  • Dostajesz inny błąd kompilacji. sznurek.h był potrzebny i nie jest zawarte pośrednio, więc include był poprawny na początku.

Zauważ, że w zależności od pośredniego włączenia, gdy twój .h lub .c bezpośrednio wykorzystuje kolejny .h jest prawie z pewnością błąd: w efekcie obiecujesz, że Twoje kod będzie wymagał tego nagłówka tylko tak długo, jak długo używasz innego nagłówka wymaga tego, co pewnie nie o to ci chodziło.

Zastrzeżenia wymienione w innych odpowiedziach na temat nagłówków modyfikujących zachowanie raczej to, że deklarowanie rzeczy, które powodują błędy budowania, stosuje się również tutaj.

 0
Author: Britton Kerin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-10 22:12:07