127 Stimmen

Tools zur Erstellung eines Funktionsaufrufdiagramms von Code

Ich habe einen großen Arbeitsbereich, der viele Quelldateien mit C-Code enthält. Obwohl ich die Funktionen sehen kann, die von einer Funktion in MS VS2005 mit dem Objektbrowser aufgerufen werden, und in MSVC 6.0 auch, zeigt dies nur Funktionen, die von einer bestimmten Funktion in einer nicht-grafischen Art der Anzeige aufgerufen werden. Darüber hinaus zeigt es nicht die Funktion aufgerufen, beginnend mit sagen wir main() und dann die davon aufgerufenen Funktionen und so weiter, bis hin zur Funktion auf Blattebene.

Ich brauche ein Tool, das mir einen Funktionsaufrufgraphen mit Funktionen bildlich darstellt callee y caller verbunden durch Pfeile oder ähnliches, ausgehend von main() bis zur letzten Funktionsebene, oder zumindest ein Aufrufdiagramm aller Funktionen in einer C-Quelldatei bildlich darstellen. Es wäre toll, wenn ich dieses Diagramm ausdrucken könnte.

Gibt es dafür gute Tools (müssen keine kostenlosen Tools sein)?

69voto

philant Punkte 32877

34voto

Dynamische Analysemethoden

Hier beschreibe ich einige dynamische Analysemethoden.

Bei dynamischen Methoden wird das Programm tatsächlich ausgeführt, um den Aufrufgraph zu ermitteln.

Das Gegenteil von dynamischen Methoden sind statische Methoden, die versuchen, sie allein aus dem Quelltext zu ermitteln, ohne das Programm auszuführen.

Vorteile der dynamischen Methoden:

  • fängt Funktionszeiger und virtuelle C++-Aufrufe ab. Diese sind in großer Zahl in jeder nicht-trivialen Software vorhanden.

Nachteile der dynamischen Methoden:

  • Sie müssen das Programm ausführen, was langsam sein kann oder ein Setup erfordert, das Sie nicht haben, z. B. Cross-Compilation
  • werden nur Funktionen angezeigt, die tatsächlich aufgerufen wurden. Einige Funktionen könnten z.B. abhängig von den Befehlszeilenargumenten aufgerufen werden oder nicht.

KcacheGrind

https://kcachegrind.github.io/html/Home.html

Testprogramm:

int f2(int i) { return i + 2; }
int f1(int i) { return f2(2) + i + 1; }
int f0(int i) { return f1(1) + f2(2); }
int pointed(int i) { return i; }
int not_called(int i) { return 0; }

int main(int argc, char **argv) {
    int (*f)(int);
    f0(1);
    f1(1);
    f = pointed;
    if (argc == 1)
        f(1);
    if (argc == 2)
        not_called(1);
    return 0;
}

Verwendung:

sudo apt-get install -y kcachegrind valgrind

# Compile the program as usual, no special flags.
gcc -ggdb3 -O0 -o main -std=c99 main.c

# Generate a callgrind.out.<PID> file.
valgrind --tool=callgrind ./main

# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234

Sie befinden sich nun in einem fantastischen GUI-Programm, das eine Menge interessanter Leistungsdaten enthält.

Wählen Sie unten rechts die Registerkarte "Anrufdiagramm". Hier wird ein interaktives Anrufdiagramm angezeigt, das beim Anklicken der Funktionen mit Leistungskennzahlen in anderen Fenstern korreliert.

Um das Diagramm zu exportieren, klicken Sie es mit der rechten Maustaste an und wählen Sie "Grafik exportieren". Das exportierte PNG sieht wie folgt aus:

Daran können wir erkennen, dass:

  • der Wurzelknoten ist _start der den eigentlichen ELF-Einstiegspunkt darstellt und Glibc-Initialisierungs-Boilerplate enthält
  • f0 , f1 y f2 werden wie erwartet voneinander abgerufen
  • pointed wird ebenfalls angezeigt, obwohl wir sie mit einem Funktionszeiger aufgerufen haben. Sie wäre möglicherweise nicht aufgerufen worden, wenn wir ein Kommandozeilenargument übergeben hätten.
  • not_called wird nicht angezeigt, weil es im Lauf nicht aufgerufen wurde, weil wir kein zusätzliches Kommandozeilenargument übergeben haben.

Das Tolle an valgrind ist, dass es keine besonderen Kompilierungsoptionen erfordert.

Daher können Sie es auch dann verwenden, wenn Sie nicht über den Quellcode, sondern nur über die ausführbare Datei verfügen.

valgrind schafft das, indem es Ihren Code durch eine leichtgewichtige "virtuelle Maschine" laufen lässt. Dies macht die Ausführung im Vergleich zur nativen Ausführung auch extrem langsam.

Wie in der Grafik zu sehen ist, werden auch Zeitinformationen über jeden Funktionsaufruf ermittelt, die zur Erstellung eines Programmprofils verwendet werden können, was wahrscheinlich der ursprüngliche Verwendungszweck dieser Einrichtung ist, und nicht nur zur Anzeige von Aufrufgraphen: Wie kann ich ein Profil für C++-Code erstellen, der unter Linux läuft?

Getestet auf Ubuntu 18.04.

gcc -finstrument-functions + etrace

https://github.com/elcritch/etrace

-finstrument-functions fügt Rückrufe hinzu parst etrace die ELF-Datei und implementiert alle Rückrufe.

Ich konnte es aber leider nicht zum Laufen bringen: Warum funktioniert `-finstrument-functions` bei mir nicht?

Die angegebene Ausgabe hat das Format:

\-- main
|   \-- Crumble_make_apple_crumble
|   |   \-- Crumble_buy_stuff
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   \-- Crumble_prepare_apples
|   |   |   \-- Crumble_skin_and_dice
|   |   \-- Crumble_mix
|   |   \-- Crumble_finalize
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_put
|   |   \-- Crumble_cook
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_bake

Dies ist wahrscheinlich die effizienteste Methode, abgesehen von spezieller Hardware-Tracing-Unterstützung, hat aber den Nachteil, dass Sie den Code neu kompilieren müssen.

18voto

MattK Punkte 10147

Verstehen Sie leistet sehr gute Arbeit bei der Erstellung von Anrufdiagrammen.

12voto

Ira Baxter Punkte 91118

Unser DMS-Software-Reengineering-Werkzeugsatz hat statische Kontroll-/Datenfluss-/Punkt-/Aufrufdiagramm-Analyse das auf riesige Systeme (~~25 Millionen Zeilen) von C-Code angewandt wurde und solche Aufrufdiagramme erzeugte, einschließlich Funktionen, die über Funktionszeiger aufgerufen werden .

11voto

Fabio Visona' Punkte 101

Sie können CScope + ausprobieren. tceetree + Graphviz .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X