it-swarm.com.de

Überflüssige #inhalte in C/C++ erkennen?

Ich finde oft, dass die Kopfzeilen einer Datei immer größer werden, aber niemals kleiner. Während der gesamten Lebensdauer einer Quelldatei konnten Klassen verschoben und umgestaltet werden, und es ist sehr wahrscheinlich, dass es einige #includes gibt, die nicht mehr vorhanden sein müssen. Wenn Sie sie dort belassen, verlängert dies nur die Kompilierzeit und fügt unnötige Abhängigkeiten beim Kompilieren hinzu. Der Versuch herauszufinden, welche noch benötigt werden, kann recht mühsam sein.

Gibt es ein Werkzeug, das überflüssige # include-Direktiven erkennt und vorschlägt, welche ich sicher entfernen kann?
Macht Flusen das vielleicht?

246
shoosh

Es ist nicht automatisch, aber doxygen erzeugt Abhängigkeitsdiagramme für #included-Dateien. Sie müssen sie visuell durchgehen, aber sie können sehr nützlich sein, um ein Bild davon zu erhalten, was mit was verwendet wird.

39
anon

Googles cppclean (Links zu: download , documentation ) kann verschiedene Kategorien von C++ - Problemen finden und kann nun überflüssige # -Inhalte enthalten.

Es gibt auch ein Clang-basiertes Werkzeug, include-what-you-use , das dies tun kann. include-what-you-use kann sogar Vorwärtsdeklarationen vorschlagen (so dass Sie nicht so viel # enthalten müssen) und optional Ihre # -Inhalte für Sie bereinigen. 

Aktuelle Versionen von Eclipse CDT haben auch diese Funktion eingebaut: Wenn Sie im Source-Menü auf Organize Includes klicken, werden Ihre # include's alphabetisch sortiert, fügen Sie alle Header hinzu, die Eclipse verwendet, ohne sie direkt einzubinden, und kommentieren Sie diese aus Header, die es nicht für nötig hält. Diese Funktion ist jedoch nicht zu 100% zuverlässig.

148
Josh Kelley

Check out include-what-you-use , was ein ähnliches Problem löst. 

57
Tzafrir

Das Problem beim Erkennen überflüssiger Include-Elemente ist, dass es sich nicht nur um eine Typabhängigkeitsprüfung handeln kann. Ein überflüssiges Include ist eine Datei, die der Kompilierung nichts Wertvolles verleiht. und ändert nichts an einem anderen Element, von dem andere Dateien abhängen. Es gibt viele Möglichkeiten, wie eine Header-Datei eine Kompilierung ändern kann, z. B. durch Definieren einer Konstante, Neudefinieren und/oder Löschen eines verwendeten Makros, wobei ein Namespace hinzugefügt wird, der die Suche nach einem Namen entlang der Zeile ändert. Um Elemente wie den Namespace zu erkennen, benötigen Sie weit mehr als einen Präprozessor. Sie benötigen fast einen vollständigen Compiler. 

Lint ist eher ein Stilprüfer und wird sicherlich nicht die volle Leistungsfähigkeit haben. 

Ich denke, der einzige Weg, ein überflüssiges Include zu erkennen, besteht darin, Suites zu entfernen, zu kompilieren und auszuführen. 

24
JaredPar

Ich dachte, dass PCLint dies tun würde, aber es ist einige Jahre her, seit ich es angeschaut habe. Sie könnten es überprüfen.

Ich schaute in dieses Blog und der Autor sprach ein wenig über die Konfiguration von PCLint, um ungenutzte Includes zu finden. Vielleicht einen Blick wert.

15
itsmatt

Der Refactoring-Browser CScout kann überflüssige Include-Anweisungen in C-Code (leider nicht in C++) erkennen. Eine Beschreibung der Funktionsweise finden Sie in diesem Zeitschriftenartikel.

7

Sie können ein schnelles Skript schreiben, das eine einzelne # include-Direktive löscht, die Projekte kompiliert und den Namen in # include und die Datei protokolliert, aus der sie entfernt wurde, falls keine Kompilierungsfehler aufgetreten sind.

Lassen Sie es während der Nacht laufen, und am nächsten Tag haben Sie eine 100% korrekte Liste der Include-Dateien, die Sie entfernen können.

Manchmal funktioniert Brute-Force einfach :-)


edit: und manchmal auch nicht :-). Hier ein paar Informationen aus den Kommentaren:

  1. Manchmal können Sie zwei Header-Dateien separat entfernen, jedoch nicht beide zusammen. Eine Lösung besteht darin, die Header-Dateien während des Laufs zu entfernen und nicht zurückzubringen. Dadurch wird eine Liste von Dateien angezeigt, die Sie sicher entfernen können. Es kann jedoch eine Lösung mit mehr Dateien zum Entfernen geben, die dieser Algorithmus nicht findet. (Es ist eine gierige Suche über den Bereich der zu entfernenden Include-Dateien. Sie findet nur ein lokales Maximum.
  2. Es kann geringfügige Änderungen im Verhalten geben, wenn einige Makros je nach #ifdefs unterschiedlich definiert wurden. Ich denke, das sind sehr seltene Fälle, und die Unit-Tests, die Bestandteil des Builds sind, sollten diese Änderungen berücksichtigen.
6
Gilad Naor

Ich habe noch nie ein vollwertiges Werkzeug gefunden, mit dem Sie erreichen können, was Sie fragen. Das, was ich am häufigsten verwendet habe, ist IncludeManager , das den Header-Einschlussbaum grafisch darstellt, sodass Sie Dinge wie in nur einer Datei enthaltene Header und kreisförmige Header-Einschlüsse visuell erkennen können.

5
Dan Olson

Es tut mir leid, hier (neu) posten zu müssen. Die Leute erweitern die Kommentare oft nicht.

Überprüfen Sie meinen Kommentar zu crashmstr, FlexeLint/PC-Lint erledigt dies für Sie. Informationsnachricht 766. In Abschnitt 11.8.1 meines Handbuchs (Version 8.0) wird dies erläutert.

Auch und das ist wichtig, iteriere weiter, bis die Nachricht verschwindet . Mit anderen Worten: Nach dem Entfernen unbenutzter Header und erneutem Ausführen von Flusen sind möglicherweise mehr Headerdateien "nicht mehr erforderlich", wenn Sie einige nicht benötigte Header entfernen. (Das hört sich vielleicht dumm an, liest es langsam und parst es, es macht Sinn.)

5
Dan

Wenn Sie Eclipse CDT verwenden, können Sie http://includator.com ausprobieren, das für Betatester (zum Zeitpunkt der Erstellung dieses Dokuments) kostenlos ist und automatisch überflüssige # enthält oder fehlende entfernt. Für Benutzer, die über FlexeLint oder PC-Lint verfügen und Elicpse CDT verwenden, könnte http://linticator.com eine Option sein (auch für Betatests kostenlos). Während die Analyse von Lint verwendet wird, werden schnelle Korrekturen zum automatischen Entfernen der überflüssigen # include-Anweisungen bereitgestellt.

4
PeterSom

Um diese Diskussion zu beenden, ist der C++ - Präprozessor fertig. Es ist eine semantische Eigenschaft, ob ein Include überflüssig ist. Aus dem Satz von Rice folgt daher, dass es unentscheidbar ist, ob ein Include überflüssig ist oder nicht. Es kann NICHT ein Programm geben, das (immer richtig) erkennt, ob ein Include überflüssig ist.

2
Algoman

Es gibt ein kostenloses Tool Include File Dependencies Watcher , das in das Visual Studio integriert werden kann. Es zeigt überflüssiges # in rot an.

2
Vladimir

Dieser Artikel erläutert eine Technik zum Entfernen von #include mithilfe der Analyse von Doxygen. Das ist nur ein Perl-Skript, daher ist es sehr einfach zu benutzen.

2
Steve Gury

Ich habe es mit Flexelint (der Unix-Version von PC-Lint) versucht und hatte etwas gemischte Ergebnisse. Dies liegt wahrscheinlich daran, dass ich an einer sehr großen und knotigen Codebasis arbeite. Ich empfehle, jede Datei, die als nicht verwendet gemeldet wird, sorgfältig zu prüfen.

Die Hauptsorge ist falsch positiv. Mehrere Includes desselben Headers werden als nicht benötigter Header gemeldet. Dies ist schlecht, da Flexelint Ihnen nicht sagt, in welcher Zeile der Header enthalten ist oder wo er zuvor eingefügt wurde.

Eine der Möglichkeiten, mit der automatisierte Tools das falsch machen können:

In A.hpp:

class A { 
  // ...
};

In B.hpp:

#include "A.hpp

class B {
    public:
        A foo;
};

In 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

Wenn Sie den Nachrichten von Flexelint blind folgen, werden Sie Ihre Abhängigkeiten mit #include aufmischen. Es gibt mehr pathologische Fälle, aber im Grunde müssen Sie die Header selbst überprüfen, um beste Ergebnisse zu erzielen.

Ich empfehle diesen Artikel zu Physical Structure und C++ aus den Blog-Spielen von innen. Sie empfehlen einen umfassenden Ansatz zur Beseitigung des Chaos von #include:

Richtlinien

Hier finden Sie eine Reihe von Richtlinien aus dem Buch von Lakos, die die Anzahl der physischen Abhängigkeiten zwischen Dateien minimieren. Ich benutze sie seit Jahren und war mit den Ergebnissen immer sehr zufrieden.

  1. Jede cpp-Datei enthält zuerst eine eigene Header-Datei. [schnippen]
  2. Eine Header-Datei muss alle Header-Dateien enthalten, die zum Analysieren erforderlich sind. [schnippen]
  3. Eine Header-Datei sollte über die minimale Anzahl von Header-Dateien verfügen, die zum Analysieren erforderlich sind. [schnippen]
2
Ben Martin

Hier ist eine einfache brute force-Methode zum Identifizieren überflüssiger Header-Includes . Es ist nicht perfekt, eliminiert jedoch die "offensichtlichen" unnötigen Einschlüsse. Wenn Sie diese Informationen entfernen, können Sie den Code aufräumen.

Auf die scripts kann direkt über GitHub zugegriffen werden.

1
ap-osd

Vielleicht etwas spät, aber ich habe einmal ein WebKit-Perl-Skript gefunden, das genau das tat, was Sie wollten. Ich glaube, ich brauche ein paar Anpassungen (ich bin nicht mit Perl vertraut), aber es sollte den Trick tun:

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

(Dies ist ein alter Zweig, da Trunk die Datei nicht mehr besitzt.)

1
rubenvb

Es gibt zwei Arten von überflüssigen # include-Dateien:

  1. Eine Header-Datei, die von Dem Modul (.c, .cpp) überhaupt nicht benötigt wird 
  2. Eine Header-Datei wird vom Modul .__ benötigt, sie wird jedoch mehr als einmal direkt oder indirekt enthalten.

Nach meiner Erfahrung gibt es zwei Möglichkeiten, die es gut erkennen können:

  • gcc -H oder cl.exe/showincludes (Problem 2 beheben)

    In der Praxis können CFLAGS = -H vor make, Exportiert werden, wenn nicht alle Makefile-Optionen die CFLAGS-Optionen überschreiben. Oder, wie ich es verwendet habe, können Sie einen C++ - Wrapper erstellen, um die Optionen -H Zwangsweise zu jedem Aufruf von $ (CC) und $ (CXX) hinzuzufügen. und stellen Sie das Verzeichnis wrapper der Variablen $ PATH voran. Dann werden alle von Ihnen erstellt. Natürlich sollte Ihr Wrapper den Real gcc-Compiler aufrufen. Diese Tricks Müssen geändert werden, wenn Ihr Makefile Gcc direkt verwendet. anstelle von $ (CC) oder $ (CXX) oder durch implizierte Regeln.

    Sie können eine einzelne Datei auch kompilieren, indem Sie die Befehlszeile verwenden. Aber wenn Sie die Header für das gesamte Projekt löschen möchten. Sie können alle Ausgaben erfassen, indem Sie:

    mach sauber

    mach 2> & 1 | tee result.txt

  • PC-Lint/FlexeLint (Problem 1 und 2 beheben.)

    stellen Sie sicher, dass Sie die + e766-Optionen hinzufügen. Diese Warnung betrifft: ungenutzte Header-Dateien.

    pclint/flint -vf ...

    Dies führt dazu, dass die pclint-Ausgabe Header-Dateien enthält. Verschachtelte Header-Dateien werden entsprechend eingerückt.

1
zhaorufei

PC Lint von Gimpel Software kann berichten, wenn eine Include-Datei mehr als einmal in eine Kompilierungseinheit aufgenommen wurde, aber es kann keine Include-Dateien finden, die bei der Suche nicht benötigt werden.

Bearbeiten: Es kann. Siehe die Antwort von itsmatt

0
crashmstr

CLion , das C/C++ IDE von JetBrains, erkennt redundante Include-of-the-Box. Diese sind im Editor ausgegraut, aber es gibt auch Funktionen für Optimierungen umfassen die aktuelle Datei oder das gesamte Projekt .

Ich habe jedoch festgestellt, dass Sie für diese Funktionalität bezahlen. CLion benötigt beim ersten Laden eine Weile, um Ihr Projekt zu scannen und zu analysieren.

0
congusbongus