Frage

Gibt es eine Möglichkeit zu wissen, und gibt die Stapelgröße durch eine Funktion bei der Kompilierung in C benötigt? Hier ist, was würde ich gerne wissen:

Lassen Sie uns einige Funktion übernehmen:

void foo(int a) {
    char c[5];
    char * s;
    //do something
    return;
}

Wenn Sie diese Funktion kompilieren, würde Ich mag wissen, wie viel Stapelspeicher es verbraucht whent sie aufgerufen wird. Dies könnte nützlich sein, die auf Stapel Deklaration einer Struktur zu erkennen, einen großen Puffer versteckt.

Ich bin auf der Suche nach etwas, das so etwas wie dieser drucken würde:

Datei foo.c: function foo Stackverbrauch ist n Bytes

Gibt es eine Möglichkeit nicht an der generierten Assembly zu suchen, das zu wissen? Oder eine Grenze, die für den Compiler gesetzt werden kann?

Update: Ich bin nicht versuchen Runtime Stack-Überlauf für einen bestimmten Prozess zu vermeiden, ich bin auf der Suche nach einer Möglichkeit, vor der Laufzeit zu finden, wenn eine Funktion Stack-Nutzung, wie vom Compiler bestimmt, als eine Ausgabe der Compilation zur Verfügung Prozess.

Lassen Sie uns es anders auszudrücken: Ist es möglich, die Größe aller Objekte lokal zu einer Funktion wissen? Ich denke, Compiler-Optimierung wird nicht mein Freund sein, weil einige Variablen verschwinden aber eine obere Grenze ist in Ordnung.

War es hilfreich?

Lösung

Linux-Kernel-Code läuft auf einem 4K-Stack auf x86. Daher kümmern sie. Was sie verwenden, das zu überprüfen, ist ein Perl-Skript, sie schrieben, die Sie als scripts / checkstack.pl in einem aktuellen Kernel-Tarball (es 2.6.25 vor) finden können. Es läuft auf dem Ausgang von objdump, Verwendung Dokumentation ist in dem Anfang Kommentar.

Ich glaube, ich habe es schon für User-Space-Binärdateien vor Ewigkeiten, und wenn Sie ein wenig von Perl-Programmierung kennen, ist es einfach zu beheben, wenn es defekt ist.

Wie auch immer, was es im Grunde tut, ist automatisch bei GCC Ausgang zu suchen. Und die Tatsache, dass die Kernel-Hacker ein solches Tool geschrieben bedeutet, dass es keine statische Art und Weise ist es mit GCC zu tun (oder vielleicht, dass es vor kurzem hinzugefügt wurde, aber ich bezweifle, so).

Btw, mit objdump vom mingw Projekt und ActivePerl oder mit Cygwin, sollten Sie in der Lage zu tun, dass auch unter Windows und auch auf Binärdateien mit anderen Compilern erhalten.

Andere Tipps

StackAnlyser scheint den ausführbaren Code selbst plus einige Debug-Informationen zu examinate. Was von diese Antwort beschrieben wird, ist das, was ich suche, Stapel Analysator sieht aus wie viel des Guten für mich.

Etwas ähnlich dem, was für ADA besteht wäre in Ordnung. Schauen Sie sich dieses Handbuch Seite aus dem Handbuch gnat:

22,2 Statische Stapel Nutzungsanalyse

Eine Einheit zusammengestellt mit -fstack-Nutzung wird eine zusätzliche Datei erzeugen, die die maximale Menge an Stapeln legen verwendet, auf einer Pro-Funktion Basis. Die Datei hat den gleichen Basisnamen als Zielobjekt-Datei mit einer .su Erweiterung. Jede Zeile dieser Datei besteht aus drei Bereichen:

* The name of the function.
* A number of bytes.
* One or more qualifiers: static, dynamic, bounded. 

Das zweite Feld entspricht die Größe des bekannten Teils des Funktionsrahmens.

Die Qualifier Statisch bedeutet, dass die Funktion Rahmengröße rein statisch ist. Es bedeutet in der Regel, dass alle lokalen Variablen eine statische Größe haben. In diesem Fall ist das zweite Feld ein zuverlässiges Maß für die Funktion Stapelnutzung.

Der Qualifier dynamische bedeutet, dass die Funktion Rahmengröße nicht statisch ist. Es geschieht vor allem, wenn einige lokale Variablen eine dynamische Größe haben. Wenn dieser Qualifier allein erscheint, ist das zweite Feld kein zuverlässiges Maß für die Funktion Stapelanalyse. Wenn es mit beschränktem qualifiziert ist, bedeutet dies, daß das zweite Feld eine zuverlässige Maximum der Funktion Stapelnutzung ist.

Ich sehe nicht, warum eine statische Code-Analyse nicht gut genug Figur dafür geben könnte.

Es ist trivial, all lokalen Variablen in einer bestimmten Funktion zu finden, und die Größe für jede Variable kann entweder über den C-Standard (für den Einbau in Typen) oder durch Berechnung (für komplexe Typen wie Strukturen und Gewerkschaften) zu finden.

Klar, kann die Antwort nicht zu 100% garantiert präzise sein, da der Compiler verschiedene Arten von Optimierungen wie padding tun kann, Variablen in Registern zu bringen oder völlig unnötig Variablen entfernen. Aber jede Antwort gibt es sollte eine gute Schätzung zumindest sein.

Ich habe eine schnelle Google-Suche und gefunden Stack aber meine Vermutung ist, dass andere statische Code-Analyse Werkzeuge haben ähnliche Funktionen.

Wenn Sie eine 100% genaue Zahl wollen, dann würden Sie am Ausgang des Compilers suchen müssen oder überprüfen Sie es während der Laufzeit (wie Ralph in vorgeschlagen seine Antwort )

Nur der Compiler würde wirklich wissen, da es der Mann ist, die zusammen alle deine Sachen macht. Sie würden an der generierten Assembly suchen und sehen, wie viel Platz in der Präambel reserviert ist, aber das erklärt nicht wirklich für Dinge wie alloca die zur Laufzeit machen ihr Ding.

Angenommen, Sie auf einer Embedded-Plattform sind, könnten Sie feststellen, dass Ihre Werkzeugkette geht an diese hat. Gute kommerzielle Embedded-Compiler (wie zum Beispiel der Arm / Keil-Compiler) produzieren häufig Berichte von Stackverbrauch.

Natürlich Interrupts und Rekursion sind in der Regel etwas über sie, aber es gibt Ihnen eine grobe Vorstellung, wenn jemand etwas schrecklich Schraube-up mit einem Multi-Megabyte-Puffer auf dem Stack irgendwo begangen hat.

Nicht gerade „kompilieren Zeit“, aber ich würde dies als eine Post-Build-Schritt tun:

  • lassen der Linker eine Map-Datei für Sie erstellen
  • für jede Funktion in der Map-Datei las die ausführbare Datei den entsprechenden Teil, und die Funktion Prolog analysiert.

Dies ist ähnlich zu dem, was Stack tut, aber viel einfacher. Ich denke, die Analyse der ausführbaren Datei oder der Demontage ist der einfachste Weg, um den Compiler Ausgabe erhalten können. Während der Compiler diese Dinge intern weiß, ich fürchte, Sie nicht in der Lage sein wird, sie davon zu bekommen (man könnte den Compiler-Anbieter bitten, die Funktionalität zu implementieren, oder wenn Open-Source-Compiler verwenden, können Sie es selbst tun oder jemand es tun lassen für Sie).

Um dies zu implementieren, müssen Sie:

  • der Lage sein, Map-Datei
  • analysieren
  • verstehen Format der ausführbaren Datei
  • wissen, was eine Funktion Prolog aussehen kann und in der Lage zu „entschlüsseln“ it

Wie einfach oder schwierig wäre dies hängt von der Zielplattform. (Embedded? Welche CPU-Architektur? Welche Compiler?)

auf jeden Fall All dies kann in x86 / Win32 getan werden, aber wenn man so etwas noch nie gemacht und haben alles aus dem Grund auf neu zu erstellen, kann es ein paar Tage dauern, bis Sie fertig sind und etwas Arbeits haben.

Nicht im Allgemeinen. Das Halteproblem in der theoretischen Informatik legt nahe, dass man nicht einmal vorhersagen kann, ob ein allgemeines Programm auf einem bestimmten Eingang stoppt. den Stapel der Berechnung für einen Programmdurchlauf im allgemeinen verwendet wird, würde noch komplizierter sein. Also: nein. Vielleicht in besonderen Fällen.

Angenommen, Sie haben eine rekursive Funktion, deren Rekursionstiefe haben, hängt von der Eingabe, die von beliebiger Länge sein kann, und Sie sind schon kein Glück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top