Erkennung von totem Code in einem älteren C / C ++ - Projekt [geschlossen]

68

Wie würden Sie die Erkennung von totem Code in C / C ++ - Code durchführen? Ich habe eine ziemlich große Codebasis, mit der ich arbeiten kann, und mindestens 10-15% sind toter Code. Gibt es ein Unix-basiertes Tool, um diese Bereiche zu identifizieren? Einige Codeteile verwenden immer noch viel Präprozessor. Kann ein automatisierter Prozess damit umgehen?

Nazgob
quelle
2
Es gibt eine ähnliche Frage mit mehr Aktivität hier: stackoverflow.com/questions/4813947/…
Mr Shark

Antworten:

30

Sie können hierfür ein Tool zur Analyse der Codeabdeckung verwenden und nach nicht verwendeten Stellen in Ihrem Code suchen.

Ein beliebtes Tool für die gcc-Toolchain ist gcov zusammen mit dem grafischen Frontend lcov ( http://ltp.sourceforge.net/coverage/lcov.php ).

Wenn Sie gcc verwenden, können Sie mit gcov-Unterstützung kompilieren, die durch das Flag '--coverage' aktiviert wird. Führen Sie als Nächstes Ihre Anwendung oder Ihre Testsuite mit diesem gcov-fähigen Build aus.

Grundsätzlich gibt gcc während der Kompilierung einige zusätzliche Dateien aus, und die Anwendung gibt während der Ausführung auch einige Abdeckungsdaten aus. Sie müssen alle diese (.gcdo- und .gcda-Dateien) sammeln. Ich werde hier nicht im Detail darauf eingehen, aber Sie müssen wahrscheinlich zwei Umgebungsvariablen festlegen, um die Abdeckungsdaten auf vernünftige Weise zu erfassen: GCOV_PREFIX und GCOV_PREFIX_STRIP ...

Nach dem Lauf können Sie alle Abdeckungsdaten zusammenstellen und über die lcov-Toolsuite ausführen. Das Zusammenführen aller Coverage-Dateien aus verschiedenen Testläufen ist ebenfalls möglich, wenn auch etwas aufwendig.

Wie auch immer, Sie erhalten eine schöne Reihe von Webseiten mit Informationen zur Abdeckung, die auf die Codeteile hinweisen, die keine Abdeckung haben und daher nicht verwendet wurden.

Natürlich müssen Sie überprüfen, ob die Teile des Codes in keiner Situation verwendet werden, und vieles hängt davon ab, wie gut Ihre Tests die Codebasis ausüben. Aber zumindest wird dies eine Vorstellung von möglichen Dead-Code-Kandidaten geben ...

Johan
quelle
Ich bin immer noch mit Sun C ++ - Compilern beschäftigt, aber wir haben eine gcc-Migration im Gange, also werde ich das ausprobieren. Vielen Dank.
Nazgob
Eine Code-Coverage-Analyse (z. B. gcov) kann Daten liefern, deren Code nicht von den jeweiligen Läufen der Software abgedeckt wird - Code, der nicht abgedeckt wird, ist nicht unbedingt toter Code. Eine andere Ausführung der Software (z. B. eine andere Kompilierungsoption, eine andere Laufzeitoption oder andere Eingabedaten) oder ein anderer Ausführungspfad (z. B. eine Fehlerbehandlung) kann eine Funktion auslösen, die zuvor nicht aufgerufen wurde.
Arun
17

Kompilieren Sie es unter gcc mit -Wunreachable-Code.

Ich denke, je neuer die Version, desto bessere Ergebnisse werden Sie erzielen, aber ich kann mich in meinem Eindruck irren, dass sie aktiv daran gearbeitet haben. Beachten Sie, dass dies eine Flussanalyse ist, aber ich glaube nicht, dass es Sie über "Code" informiert, der zum Zeitpunkt des Verlassens des Präprozessors bereits tot ist, da dies vom Compiler nie analysiert wird. Es werden auch keine exportierten Funktionen erkannt, die niemals aufgerufen werden, oder Code für die Behandlung von Sonderfällen, der einfach so unmöglich ist, weil die Funktion mit diesem Parameter nie aufgerufen wird - dafür benötigen Sie Codeabdeckung (und führen die Funktionstests nicht aus die Unit-Tests. Unit-Tests sollen100% Codeabdeckung haben und daher Codepfade ausführen, die für die Anwendung "tot" sind). Angesichts dieser Einschränkungen ist es jedoch eine einfache Möglichkeit, die am vollständigsten bollixierten Routinen in der Codebasis zu finden.

In diesem CERT-Hinweis werden einige andere Tools zur Erkennung statischen toten Codes aufgeführt

Steve Jessop
quelle
3
Diese Antwort ist nicht mehr gültig, da die Option -Wunreachable-Code aus gcc entfernt wurde. gcc.gnu.org/ml/gcc-help/2011-05/msg00360.html
philippe lhardy
Schande. Für viele Zwecke ist die "instabile" Erkennung von totem Code immer noch besser als nichts. Abgesehen von allem anderen ist eine perfekte Erkennung von totem Code im Allgemeinen nicht möglich (Problem beim Anhalten), sodass jeder weiß, dass das von ihm verwendete Tool nicht perfekt ist. Vermutlich kümmert sich tatsächlich jemand darum, dass es unvollkommener ist -O0als mit -O3oder möchte keine neuen Warnungen, wenn sich das Optimierungsprogramm verbessert.
Steve Jessop
3
Wenn Ihr Code keine neuen Funktionen verwendet, können Sie dennoch einen alten gcc als statisches Analysetool verwenden. Meine Antwort ist also nicht ganz falsch. Ein bisschen Reichweite, ich weiß ;-)
Steve Jessop
4

Ihr Ansatz hängt von den Verfügbarkeitstests (automatisiert) ab. Wenn Sie über eine Testsuite verfügen, der Sie vertrauen, um eine ausreichende Menge an Funktionen abzudecken, können Sie eine Abdeckungsanalyse verwenden, wie bereits in früheren Antworten vorgeschlagen.

Wenn Sie nicht so viel Glück haben, sollten Sie sich mit Quellcode-Analysetools wie SciTools 'Understand befassen , mit denen Sie Ihren Code mithilfe vieler integrierter Analyseberichte analysieren können. Meine Erfahrung mit diesem Tool stammt aus dem Jahr vor zwei Jahren, daher kann ich Ihnen nicht viele Details nennen. Ich erinnere mich jedoch daran, dass sie eine beeindruckende Unterstützung mit sehr schnellen Bearbeitungszeiten von Fehlerkorrekturen und Antworten auf Fragen hatten.

Ich habe eine Seite gefunden statischen Quellcode-Analyse gefunden , auf der auch viele andere Tools aufgeführt sind.

Wenn Ihnen das auch nicht ausreichend hilft und Sie speziell daran interessiert sind, den Präprozessor-bezogenen toten Code herauszufinden, würde ich Ihnen empfehlen, weitere Details zum Code zu veröffentlichen. Wenn es sich zum Beispiel hauptsächlich um verschiedene Kombinationen von # ifdef-Einstellungen handelt, können Sie Skripte schreiben, um die (Kombinationen von) Einstellungen zu bestimmen und herauszufinden, welche Kombinationen niemals tatsächlich erstellt werden usw.

andreas buykx
quelle
4

g ++ 4.01 -Wunreachable-Code warnt vor Code, der innerhalb einer Funktion nicht erreichbar ist, warnt jedoch nicht vor nicht verwendeten Funktionen.

int foo() { 
    return 21; // point a
}

int bar() {
  int a = 7;
  return a;
  a += 9;  // point b
  return a;
}

int main(int, char **) {
    return bar();
}

g ++ 4.01 gibt eine Warnung zu Punkt b aus, sagt jedoch nichts über foo () (Punkt a) aus, obwohl es in dieser Datei nicht erreichbar ist. Dieses Verhalten ist korrekt, aber enttäuschend, da ein Compiler nicht wissen kann, dass die Funktion foo () in keiner anderen Kompilierungseinheit als extern deklariert und von dort aus aufgerufen wird. Nur ein Linker kann sicher sein.

Thomas L Holaday
quelle
4

Starten Sie eine Analyse mit dem Open Source-Tool Frama-C, wenn Sie nur C-Code verwenden und davon ausgehen, dass der Quellcode des gesamten Projekts verfügbar ist . Jede Anweisung des Programms, die in der GUI rot angezeigt wird, ist toter Code.

Wenn Sie Probleme mit "totem Code" haben, können Sie auch daran interessiert sein, "Ersatzcode" zu entfernen, Code, der ausgeführt wird, aber nicht zum Endergebnis beiträgt. Dies erfordert eine genaue Modellierung der E / A-Funktionen (Sie möchten keine Berechnung entfernen, die als "sparsam" erscheint, aber als Argument dafür verwendet wird printf). Frama-C bietet die Möglichkeit, auf Ersatzcode hinzuweisen.

Pascal Cuoq
quelle
4

Sowohl Mozilla als auch Open Office verfügen über eigene Lösungen.

Max Lybbert
quelle
Beide Links sind jetzt nicht mehr zugänglich. Kann jemand aktualisieren?
Syam
2
Ich habe den ersten Link von einem Blog-Beitrag zu einer (hoffentlich länger anhaltenden) Dokumentationsseite gewechselt. Der Open Office-Link scheint zu funktionieren.
Max Lybbert
3

Eine solche Dead-Code-Analyse erfordert eine globale Analyse Ihres gesamten Projekts. Sie können diese Informationen nicht erhalten, indem Sie Übersetzungseinheiten einzeln analysieren (Sie können tote Entitäten erkennen, wenn sie sich vollständig in einer einzelnen Übersetzungseinheit befinden, aber ich denke nicht, dass Sie wirklich danach suchen).

Wir haben unser DMS Software Reengineering Toolkit verwendet, um genau dies für Java-Code zu implementieren, indem wir alle beteiligten Kompilierungseinheiten gleichzeitig analysiert, Symboltabellen für alles erstellt und alle Referenzen verfolgt haben. Eine Definition der obersten Ebene ohne Referenzen und ohne Anspruch, ein externes API-Element zu sein, ist tot. Dieses Tool entfernt auch automatisch den toten Code, und am Ende können Sie auswählen, was Sie möchten: den Bericht über tote Entitäten oder den Code, der von diesen Entitäten entfernt wurde.

DMS analysiert C ++ auch in verschiedenen Dialekten (EDIT Feb 2014: einschließlich MS- und GCC-Versionen von C ++ 14 [EDIT Nov 2017: jetzt C ++ 17] ) und erstellt alle erforderlichen Symboltabellen. Von diesem Punkt aus wäre es unkompliziert, die toten Referenzen aufzuspüren. DMS könnte auch verwendet werden, um sie zu entfernen. Siehe http://www.semanticdesigns.com/Products/DMS/DMSToolkit.html

Ira Baxter
quelle
1

Bullseye Coverage Tool würde helfen. Es ist jedoch nicht kostenlos.

Ashwin
quelle
Ist es Geld wert? Irgendwelche Erfahrungen damit? Sie haben eine Testversion, damit ich sie überprüfen kann. Wenn sie funktioniert, können wir sie kaufen :)
Nazgob
Ja .. Ich habe auf Symbian Platform verwendet ... Es ist definitiv einen Kauf wert
Ashwin