Rekursion vermeiden... Wieso?
-
*seufz*
Jetzt sind wir wieder ganz am Anfang angelangt, der ganze schöne Thread war also für nichts.
Naja, es kann nicht jeder alles verstehen.
Dabei steht doch schon in der Bibel "Du sollst nicht Stapel überlaufen" (oder so ähnlich).
-
hustbaer schrieb:
In C++ kommt übrigens auch noch etwas dazu: das Stack-Unwinding. Schreib mal eine Klasse mit dtor, wo der dtor sagen wir mal 10KB Stack braucht.
Dann nimm den Code von fricky, und leg in "crash" eine lokale Instanz dieser Klasse an.
Und dann guck, ob das Programm das überlebt.ich schätze das wird es, denn das __try merkt sich den ESP vorm funktionsaufruf, sollte also egal sein, was die funktion mit dem stack anstellt. schon mal ausprobiert?
Bashar schrieb:
Das heißt Rekursion ist ein Programmierfehler.
rekursion, ohne die rekursionstiefe zu berücksichtigen, ist ein programmierfehler. aber zum glück brauchen sinnvolle rekursive algos garnicht so viel stackspeicher wie's scheint.
-
hustbaer schrieb:
Jetzt sind wir wieder ganz am Anfang angelangt, der ganze schöne Thread war also für nichts.
Wir waren die ganze Zeit am Anfang. Ich wollte nur nochmal wissen, ob du das wirklich meinst, was du die ganze Zeit andeutest.
Dabei steht doch schon in der Bibel "Du sollst nicht Stapel überlaufen" (oder so ähnlich).
Mir doch egal was die Schweizer abstimmen.
-
;fricky schrieb:
hustbaer schrieb:
In C++ kommt übrigens auch noch etwas dazu: das Stack-Unwinding. Schreib mal eine Klasse mit dtor, wo der dtor sagen wir mal 10KB Stack braucht.
Dann nimm den Code von fricky, und leg in "crash" eine lokale Instanz dieser Klasse an.
Und dann guck, ob das Programm das überlebt.ich schätze das wird es, denn das __try merkt sich den ESP vorm funktionsaufruf, sollte also egal sein, was die funktion mit dem stack anstellt. schon mal ausprobiert?
Er kann sich ESP und EBP merken und dazu noch in dreifacher Ausfertigung ausdrucken und es wird nix bringen. Der Dtor muss laufen, bevor der Stack-Pointer zurückgesetzt wird, da das zu zerstörende Objekt ja schliesslich auf dem Stack liegt. Ergebnis: BUMM.
Folgendes Programm:
#include <windows.h> #include <stdio.h> class needs_muchos_stackos_in_dtor { public: ~needs_muchos_stackos_in_dtor() { char muchos_stackos[10 * 1024]; strcpy(muchos_stackos, "~needs_muchos_stackos_in_dtor\n"); ::OutputDebugStringA(muchos_stackos); } char some_wasted_space_to_speed_things_up[50]; }; int recusrion() { needs_muchos_stackos_in_dtor nms; if (::GetVersion() == 0) return 123; else return recusrion() + recusrion(); } int main(int argc, char* args[]) { __try { printf("%d\n", recusrion()); } __except (EXCEPTION_EXECUTE_HANDLER) { ::OutputDebugStringA("__except\n"); } }
Ergebnis mit /EHsc:
First-chance exception at 0x00cf1407 in vc9test.exe: 0xC00000FD: Stack overflow. __except The program '[876] vc9test.exe: Native' has exited with code 0 (0x0).
Der Dtor wird wie erwartet nicht ausgeführt, da /EHsc. Das Programm verhält sich nicht korrekt, da auf den Dtor geschissen wurde. Inakzeptabel.
Ergebnis mit /EHa:
First-chance exception at 0x00d21407 in vc9test.exe: 0xC00000FD: Stack overflow. First-chance exception at 0x00d219c7 in vc9test.exe: 0xC0000005: Access violation reading location 0x00150000. First-chance exception at 0x00d219c7 in vc9test.exe: 0xC0000005: Access violation reading location 0x00150000. First-chance exception at 0x00d219c7 in vc9test.exe: 0xC0000005: Access violation reading location 0x00150000. Unhandled exception at 0x00d219c7 in vc9test.exe: 0xC0000005: Access violation reading location 0x00150000. The program '[5012] vc9test.exe: Native' has exited with code -1073741819 (0xc0000005).
Bumm. Inakzeptabel.
Noch Fragen?
-
hustbaer schrieb:
Er kann sich ESP und EBP merken und dazu noch in dreifacher Ausfertigung ausdrucken und es wird nix bringen. Der Dtor muss laufen, bevor der Stack-Pointer zurückgesetzt wird, da das zu zerstörende Objekt ja schliesslich auf dem Stack liegt. Ergebnis: BUMM.
ein 'bumm' ist es ja eben nicht, wenn du die exception geeignet abfängst.
hustbaer schrieb:
Das Programm verhält sich nicht korrekt, da auf den Dtor geschissen wurde
das ist allerdings wahr.
hustbaer schrieb:
Noch Fragen?
nö. ich könnte jetzt mal wieder ein paar ätzende bemerkungen über eine bestimmte programmiersprache machen, aber dass lasse ich diesmal.
-
;fricky schrieb:
hustbaer schrieb:
Er kann sich ESP und EBP merken und dazu noch in dreifacher Ausfertigung ausdrucken und es wird nix bringen. Der Dtor muss laufen, bevor der Stack-Pointer zurückgesetzt wird, da das zu zerstörende Objekt ja schliesslich auf dem Stack liegt. Ergebnis: BUMM.
ein 'bumm' ist es ja eben nicht, wenn du die exception geeignet abfängst.
Man kann die Exception nicht geeignet abfangen, das ist es ja gerade.
Wenn du C programmieren willst fein, programmier C. Wenn du C++ programmieren willst kannst du es aber vergessen.BTW: du kannst in C genauso probleme bekommen, wenn du __finally Blöcke verwendest die einiges an Stack brauchen.
-
hustbaer schrieb:
Man kann die Exception nicht geeignet abfangen, das ist es ja gerade.
...
du kannst in C genauso probleme bekommen, wenn du __finally Blöcke verwendest die einiges an Stack brauchen.doch, du darfst den stack erst wieder *nach* der exception benutzen, auch nicht in einem __finally-block, weil er dann noch nicht zurückgesetzt wurde. der stackoverflow-verursachende code muss immer in __try/__except eingeschlossen sein, dann wird alles wieder gut. der stackpointer erhält dann wieder den zustand, wie vor dem __try statement. alles was vorher auf dem stack war, behält weiterhin seine gültigkeit.
hustbaer schrieb:
Wenn du C++ programmieren willst kannst du es aber vergessen.
naja, aber C++ kann man auch ohne destruktoren verwenden, wenn sie solche mätzchen machen. das geht bestimmt.
-
Jungs, schreibt eure Algorithmen tail-recursive, dann kann euch nix passieren
-
;fricky schrieb:
hustbaer schrieb:
Man kann die Exception nicht geeignet abfangen, das ist es ja gerade.
...
du kannst in C genauso probleme bekommen, wenn du __finally Blöcke verwendest die einiges an Stack brauchen.doch, du darfst den stack erst wieder *nach* der exception benutzen, auch nicht in einem __finally-block, weil er dann noch nicht zurückgesetzt wurde. der stackoverflow-verursachende code muss immer in __try/__except eingeschlossen sein, dann wird alles wieder gut. der stackpointer erhält dann wieder den zustand, wie vor dem __try statement. alles was vorher auf dem stack war, behält weiterhin seine gültigkeit.
das ist theoretische und völlig unpraktikable hirnwichserei. interessiert mich kein bisschen. anwendbarkeit = 0.
hustbaer schrieb:
Wenn du C++ programmieren willst kannst du es aber vergessen.
naja, aber C++ kann man auch ohne destruktoren verwenden, wenn sie solche mätzchen machen. das geht bestimmt.
siehe oben. völlig unpraktikabel. kann ich gleich bei C bleiben.
DU magst C++ nicht, gut, bleib bei C. WENN man aber C++ verwendet, dann bitte richtig. und dann kann man keine kunstgriffe brauchen, die es einem verbieten destruktoren zu verwenden.theoretisch ist viel möglich. bloss sinnvoll ist davon nicht viel.
-
hustbaer schrieb:
das ist theoretische und völlig unpraktikable hirnwichserei. interessiert mich kein bisschen. anwendbarkeit = 0.
mannomann, natürlich bastelt sich keiner absichtliche stack-overflows oder so, aber das war nie die frage. es gibt seltene situationen, in denen sowas u.ä. vorkommen kann, und dann ist SEH eine sehr willkommene sache.
hustbaer schrieb:
WENN man aber C++ verwendet, dann bitte richtig. und dann kann man keine kunstgriffe brauchen, die es einem verbieten destruktoren zu verwenden.
was richtig oder falsch ist, kann immer noch jeder, situationsbedingt, für sich selbst entscheiden. aber diese starre schwarz/weiss-ganz-oder-garnicht haltung ist ja mal wieder typisch für dich. *cry*
-
;fricky schrieb:
hustbaer schrieb:
WENN man aber C++ verwendet, dann bitte richtig. und dann kann man keine kunstgriffe brauchen, die es einem verbieten destruktoren zu verwenden.
was richtig oder falsch ist, kann immer noch jeder, situationsbedingt, für sich selbst entscheiden.
es sollte jeder können.
wie man an dir sieht, kann es leider nicht jeder.
-
Weiß auch jemand, WARUM der Stackspeicher so beschränkt ist? Normalerweise in C und C++ nur 1MB. Vielleicht sollte man darüber nachdenken, wie man diese beschränkung loswerden kann (oder MMIX kennen).
-
Weiß auch jemand, WARUM der Stackspeicher so beschränkt ist?
Ja. Kurz: man braucht fuer gewoehnlich nicht mehr.
Normalerweise in C und C++ nur 1MB.
Beim Compiler fest einstellbar.
Vielleicht sollte man darüber nachdenken, wie man diese beschränkung loswerden kann (oder MMIX kennen).
Oder man nimmt eine Sprache mit virtueller Maschine ohne diese Beschraenkung. Aber dann jammern/mekern alle wieder ueber Performance.
-
knivil schrieb:
Weiß auch jemand, WARUM der Stackspeicher so beschränkt ist?
Ja. Kurz: man braucht fuer gewoehnlich nicht mehr.
Eigentlich habe ich die Frage gestallt, damit man drüber nachdenkt.
knivil schrieb:
Normalerweise in C und C++ nur 1MB.
Beim Compiler fest einstellbar.
Und wir beide würden wieder 1M einstellen.
knivil schrieb:
Vielleicht sollte man darüber nachdenken, wie man diese beschränkung loswerden kann (oder MMIX kennen).
Oder man nimmt eine Sprache mit virtueller Maschine ohne diese Beschraenkung. Aber dann jammern/mekern alle wieder ueber Performance.
Sagen wir mal ich hätte 2G RAM. Die Sprache mit VM wird auch abkacken wenn die 2G Ram alle sind.
Warum ist mein Stack auf 1M beschränkt, obwohl ich 2G Speicher zur Verfügung habe? Warum stelle ich das nicht um auf 2G Stackspeicher?
-
volkard schrieb:
Warum ist mein Stack auf 1M beschränkt, obwohl ich 2G Speicher zur Verfügung habe? Warum stelle ich das nicht um auf 2G Stackspeicher?
würde das nicht bedeuten, dass jeder Thread 2GB bekommt? Die werden sich ja kaum einen Stack teilen
-
zwutz schrieb:
volkard schrieb:
Warum ist mein Stack auf 1M beschränkt, obwohl ich 2G Speicher zur Verfügung habe? Warum stelle ich das nicht um auf 2G Stackspeicher?
würde das nicht bedeuten, dass jeder Thread 2GB bekommt? Die werden sich ja kaum einen Stack teilen
Ja, das wäre nett. Jeder Prozess hat ja auch 2G Heap.
-
Warum ist mein Stack auf 1M beschränkt, obwohl ich 2G Speicher zur Verfügung habe? Warum stelle ich das nicht um auf 2G Stackspeicher?
Also, mal abgesehen vom Unnutzen ist es so, dass ... aber vielleicht sollte ich keine rhetorischen Fragen beantworten ...
-
volkard schrieb:
Weiß auch jemand, WARUM der Stackspeicher so beschränkt ist? Normalerweise in C und C++ nur 1MB. Vielleicht sollte man darüber nachdenken, wie man diese beschränkung loswerden kann
die 1MB sind ja nur 'ne default-einstellung. unter windoof kannste z.b. 'CreateThread' sagen, wieviel stackspeicher du brauchst. also auch 1000 MB oder 5 bytes, wenn's sein muss.
schau hier: http://msdn.microsoft.com/en-us/library/ms686774(VS.85).aspx
-
;fricky schrieb:
volkard schrieb:
Weiß auch jemand, WARUM der Stackspeicher so beschränkt ist? Normalerweise in C und C++ nur 1MB. Vielleicht sollte man darüber nachdenken, wie man diese beschränkung loswerden kann
die 1MB sind ja nur 'ne default-einstellung. unter windows kannste z.b. 'CreateThread' sagen, wieviel stackspeicher du brauchst. also auch 1000 MB oder 5 bytes, wenn's sein muss.
schau hier: http://msdn.microsoft.com/en-us/library/ms686774(VS.85).aspxHab ich natürlich alles schon benutzt. Die Frage ist, warum tut man so gerne 1M nehmen statt 2G? Falls jemand meint, daß 2G nicht ginge, warum?
-
volkard schrieb:
Die Frage ist, warum tut man so gerne 1M nehmen statt 2G? Falls jemand meint, daß 2G nicht ginge, warum?
1MB sind wahrscheinlich ein guter kompromiss. wenn jeder thread schon beim start 2GB virtual memory für nix reservieren würde, wären weniger pages für andere dinge verfügbar.