Wie ist die Gesamtstapelgröße von einer Funktion und einem Variablenbereich abhängig?

8

Ich erhalte einen Stack-Überlauf in meinem Programm, das mit Visual Studio 2010 kompiliert wird. Ich habe einen Makro, der innerhalb eines do-while-Blocks einige string-bezogene Arbeiten mit einem kleinen Char-Array auf Stack-Basis erledigt (8 KiB) . Ich habe dann eine Funktion, wo ich dieses Makro oft im selben Umfang benutze. Und jetzt bekomme ich Stapelüberläufe.

Ich ging davon aus, dass die Stack-Zuweisung lokal für den Do-While-Block war und somit, wenn der Block endete, würde das Array aufhören zu existieren und somit nicht zur Gesamt-Stack-Nutzung der Funktion beitragen, aber es scheint, dass ich falsch lag .

Mit dem Debugger konnte ich sehen, dass beim Aufruf der Funktion _chkstk () aufgerufen wird. Als ein Argument für diese Funktion ist eine Stack-Größe etwas größer als die Summe aller 8 KiB-Arrays von jedem Aufruf des Makros in dieser Funktion (etwas größer aufgrund anderer lokaler Variablen).

Ich habe das Problem anhand eines einfachen Beispiels neu erstellt:

%Vor%

In einer einfachen Konsolenanwendung führt das Aufrufen dieser Funktion von main () zu einem Stapelüberlauf. Das Entfernen aller bis auf eine der Blockanweisungen wird jedoch problemlos funktionieren.

Ich frage mich, ob das funktioniert wie geplant?

Wie wird die Gesamtstapelgröße berechnet, die von einer Funktion benötigt wird? Wie wird die von einer Funktion benötigte Stapelgröße berechnet? Arrays auf dem Stack tragen immer noch zur Gesamt-Stack-Größe der Funktion bei, selbst nachdem sie den Bereich verlassen haben?

Warum bekomme ich einen Stapelüberlauf wenn

    
user2373744 11.05.2013, 21:57
quelle

2 Antworten

2

Ich bin ziemlich sicher, dass der Standard nicht genau definiert, wie viel Platz auf dem Stapel (oder tatsächlich, dass sie auf dem Stapel gespeichert sind), die diese Variablen benötigen. Der Compiler ist sicherlich nicht verpflichtet, für jede dieser lokalen Variablen einen Platz zuzuweisen. Die tatsächliche Wiederverwendung hängt möglicherweise auch stark von den Optimierungsstufen des Compilers ab - daher kann es verschiedene Dinge tun, wenn Sie mit verschiedenen Optimierungsebenen kompilieren (oder wenn Sie bestimmte Optimierungsfunktionen aktivieren / deaktivieren).

In C ++ werden die Aufrufe von Konstruktoren und Destruktoren für Blöcke definiert, die die Variable einschließen. Wenn Sie std::vector verwenden, wird der Speicher (der vom Heapspeicher zugewiesen wird) freigegeben, wenn der Block endet.

Zusammenfassend: Der Raum kann wiederverwendet werden, aber es ist keineswegs garantiert.

    
Mats Petersson 11.05.2013 22:09
quelle
0

Ich nehme an, das ist Compiler-spezifisch. Dasselbe gilt für GCC: Die Arrays werden aus dem Stapel entfernt, nachdem sie den Gültigkeitsbereich verlassen haben (aber es wird segfault ausgelöst, wenn alle Arrays zum selben Block gehören).

    
Inspired 11.05.2013 22:08
quelle

Tags und Links