PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Stackgröße einer Funktion


mekakic
2008-08-15, 11:18:33
Was gehört alles zur Bestimmung der Größe bzw. der maximalen Größe eines Funktionsstacks dazu bzw. was muß man summieren?

Größe des Rückgabetyps
Größe der einzelnen Funktionsparameter
Größe der angelegten Variablen
Größe aller weiteren Funktionsaufrufe

Gibt es da noch andere Punkte wo evtl. Speicher angelegt wird, ohne das dies explizit einer Variable zugeordnet wird? Kann man da überhaupt auf Quellcodeebene ausrechnen oder muß man sich dafür zwangsweise den Assembler Auswurf anschauen (evtl. legt der Compiler ja noch mehr auf dem Stack an, was man gar nicht sieht)?

Würde man im Normalfall bei diesem Code:

int foo( short x )
{
int v;
if (x>10)
{
int _v = 10;
v = _v;
}
else
{
short _v = 10;
v = _v;
}
return v;
}

Für den Funktionskopf: sizeof(int) + sizeof(short)
plus in der Funktion: (sizeof(int) + sizeof(int)) oder (sizeof(int) + sizeof(short))
bzw. beim Worstcase: (sizeof(int) + sizeof(int)) oder alles zusammen (sizeof(int) + sizeof(int) + sizeof(short))? danke

RattuS
2008-08-15, 15:22:53
Größe des Rückgabetyps
Größe der einzelnen Funktionsparameter
Größe der angelegten Variablen
Größe aller weiteren Funktionsaufrufe

Da fehlt noch die Rücksprungadresse.

ScottManDeath
2008-08-15, 15:31:00
http://69.10.233.10/KB/threads/StackWalker.aspx (codeproject) ist ein Wrapper um die Win32 Stack APIs. Da sollte was dabei sein.

Legolas
2008-08-15, 16:13:47
Also direkt auf Ebene des C-Quellcodes wirst du meiner Meinung nach keine gute obere Schranke für die Stackgröße bekommen. Der Compiler kann beim Optimieren nämlich für jede lokale Variable innerhalb einer Funktion entscheiden, ob sie überhaupt auf dem Stack landet, oder ob sie lediglich in Registern gehalten wird. Außerdem können bei komplizierten Ausdrücken theoretisch auch noch Zwischenergebnisse der Berechnung auf dem Stack landen.

Um eine aussagekräftige Grenze für die maximale Stackgröße zu bekommen, kommst du imho kaum um eine Analyse des Assemblercodes herum.

RattuS
2008-08-15, 16:57:56
push/pop innerhalb des Unterprogrammes haben aber nichts mit dem Stack des Unterprogrammes selbst zu tun. Dem TS geht ja um die Startgröße des Stackbereiches für das Unterprogramm oder? Ich bezweifle übrigens, dass der Compiler lokale Variablen intelligent in den Registern behält, allein aus dem Grund, dass, zumindest bei x86, EAX, EBX, EDX, ESI und EDI (5 der 6 Hauptregister) prinzipiell für Berechnungen und weitere Unterprogramme freigehalten werden müssen bzw. ständig gepopt/gepusht werden müssen.

PS: In der Auflistung fehlt auch noch die Größe, die beim Rücksprung anschließend wieder rausgeschmissen wird.

Legolas
2008-08-15, 17:47:28
Du kannst solches Verhalten nicht ausschliessen, zumal es immer besser ist eine Variable in einem Register zu halten, also bei jeder Benutzung auf den Speicher zugreifen zu müssen. Im 64 Bit Modus hast du dann noch zusätzliche 8 Register, was es nur noch wahrscheinlicher macht, dass häufig verwendete Variablen im Register bleiben, von anderen Zielarchitekturen mit noch mehr Registern gar nicht zu sprechen. Im Allgemeinen wird ein gut optimierender Compiler immer versuchen möglichst wenig über den Speicher gehen zu müssen, weil das langsamer ist.

Für mich hört sich es so an, als ob der Threadstarter die maximale Stackgröße statisch, also durch Codeanalyse bestimmen möchte.

mekakic
2008-08-19, 07:50:44
Für mich hört sich es so an, als ob der Threadstarter die maximale Stackgröße statisch, also durch Codeanalyse bestimmen möchte. Jo. :)

Das funktioniert auch inzwischen schon recht gut, bei meiner Analyse des Assembler Code bin ich nur auf zwei Probleme gestoßen: Funktionspointer und Rekursionen. Während ich mir bei den Funktionspointern noch einigermaßen eine Möglichkeit vorstellen könnte dies zu lösen, frage ich mich, wie man bei einer statischen ASM-Codeanalyse mit Rekursionen überhaupt umgehen kann.

Legolas
2008-08-19, 11:09:07
Jo. :)

Das funktioniert auch inzwischen schon recht gut, bei meiner Analyse des Assembler Code bin ich nur auf zwei Probleme gestoßen: Funktionspointer und Rekursionen. Während ich mir bei den Funktionspointern noch einigermaßen eine Möglichkeit vorstellen könnte dies zu lösen, frage ich mich, wie man bei einer statischen ASM-Codeanalyse mit Rekursionen überhaupt umgehen kann.

Du kannst mit Hilfe von Annotationen die maximale Rekursionstiefe vom Programmierer vorgeben lassen. Ansonsten wird es kompliziert, weil du dann den Code der rekursiven Funktion symbolisch ausführen müsstest und selbst dann kannst du nicht für alle Fälle die Rekursionstiefe ermitteln.

Problematisch könnten auch noch Schleifen sein, die z.B. ein push ohne ein pop im Schleifenrumpf ausführen. Inwieweit sowas allerdings von einem C-Compiler erzeugt wird, weiß ich auch nicht genau.