stack overflow



  • habe ein rekursives program geschrieben das soweit auch funzt solange die rekursion nicht zu tief geht. bei knapp über 3000 rekusiven aufrufen bekomme ich aber folgenden fehler:

    Unbehandelte Ausnahme bei 0x004141d7 in TableModelTest.exe: 0xC00000FD: Stack overflow.
    

    ich meine, dass das irgendwann passiert war mir klar aber bei 3000 schon? habe zum testen dann einfach mal folgendes mini-prog geschrieben:

    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    void stackTest(int k){
    	stackTest(k+1);
    }
    
    int main(void){
    
    	stackTest(0);
    
    }
    

    auch das schmiert schon bei k=4795 ab!

    kann ich den stack irgendwie vergrößern?

    habe es schon mit

    #pragma check_stack off
    

    und

    /Gs[size]
    

    versucht, hat aber beides nichts gebracht.
    ich benutze Visual Studio 2005.
    irgendwer eine idee?



  • snuuts schrieb:

    auch das schmiert schon bei k=4795 ab!

    Wen willst du eigentlich reinlegen?
    Das Programm kackt bei jedem Wert ab...



  • jo, das soll ja auch abschmieren! ich habe das ledicglich zum testen geschrieben um zu sehen, dass ich in meinem eigentlichen programm nicht irgendeinen datenmüll mit mir rumschleppe der den stack zuballert. das program schmiert bei mir schon in der 4795 iteration ab! ich habe halt das problem, dass ich SEHR SCHNELL einen stack-overflow kriege! Dass ich den irgendwann habe ist mir klar. mir geht es darum zu wissen wie ich den zeitpunkt hinauszögern , sprich den stack vergrößern kann!



  • Irgendwie sieht das nach dem falschen Lösungsweg aus.

    Warum willst Du denn den Stack vergrößern ?



  • Windows erhöht den Stack on demand auf bis zu 1 MB



  • Ok. Hab das jetzt selbst probiert. Debug Mode: 4795.
    Release Mode schmiert garnicht ab, weil der nette VC das zu ner Schleife weg-optimiert.

    Also was anderes testen:

    int g_lala = 0;
    
    int ReCursed(int rek, int blubb)
    {
    //	int lala = ::GetTickCount();
    	g_lala = rek;
    	if(rek)
    		return ReCursed(rek + 1, blubb * rek) - blubb;
    	else
    		return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	if(::GetTickCount() == 0)
    		ReCursed(::GetTickCount(), 1);
    	else
    		ReCursed(1, 1);
    
    	printf("(%d)\n", g_lala);
    	return 0;
    }
    

    Das schmiert nu wieder ab, und zwar in Tiefe 65273. Blubb. 1MB / 65273 = 16,064... - also braucht die Funktion 16 Byte Stack. Tolle Wurst, nicht grad viel zu viel. Also alles ganz normal. Du musst bloss richtig testen...

    Im Debug Mode wirds wohl deswegen früher schluss sein, weil der VC da so viel Sachen dazumacht, so Guard-Bytes etc.
    OK, ~218 Byte für eine doofe Funktion die eigentlich nix tut ist schon heftig, aber dann auch wieder egal -- wer nestet schon 4000 Levels tief?

    EDIT
    @TrollDetector:
    Windows reserviert eine bestimmte Menge Adressraum für den Stack, und zwar sofort wenn der Thread angelegt wird. Default ist 1MB ja, aber wenn man 100MB Stack haben will oder bloss 100K, dann geht das auch. Und Windows kann auch nicht zaubern wenn man bloss 100K einstellt, dann bleiben es 100K, ganz egal ob man mehr brauchen würde 😉



  • also, habe den algorithmus x von donald knuth mithilfe der dancing links implementiert um exact cover probleme zu lösen. Dieser algorithmus ist hier (http://xxx.lanl.gov/PS_cache/cs/pdf/0011/0011047.pdf) genauer erläutert. Leider erzeuge ich aber sehr große matrizen, so dass der algorithmus ziemlich excessives backtracking betreibt und für große matrizen bekomme ich halt irgendwann einen stack-overflow. ich denke auch nicht, dass sich dieser algorithmus einfach so durch einen iterativen algorithmus ersetzen lässt (wenn doch, immer her damit 😉 ) und fürchte daher, dass eine vergrößerung des stacks der einzige weg ist. falls jemanden eine bessere möglichkeit einfällt habe ich natürlich auch nichts dagegen ;).



  • meine fresse um die zeit soviele antworten, geht ihr nie pennen ? 🙄



  • Du kannst die "Basic Runtime Checks" im Debug Modus auf "Default" schalten. Im Release sind die sowieso normal nicht ein.

    Im Debug kannst du dann ja einfach mal 10MB Stack (oder mehr) einstellen. Wenn dir das Programm im Release auch abschmiert, dann kannst du ja evtl. im Release auch mehr Stack hergeben.

    Oder du implementierst selbst einen "Stack" wo du deinen State drauflegst, und wastelst die Funktion um dass sie ne Schleife verwendet, und das Backtracking eben selbst die nötigen Daten von dem "manuellen Stack" runterklaubt. Dann kannst du genau kontrollieren wieviel Speicher du pro "Frame" brauchst, und vor allem landet es nichtmehr am Stack, sondern eben im normalen Speicher.



  • @hustbär:
    Schon klar, dass man auch mehr bei der Initialisierung beantragen kann...

    Aber für den main-Thread geht das doch nciht, oder?



  • Woll geht, muss nur im PE Image entsprechend eingetragen sein. Ist ne Linkeroption. Kannste im Studio umstellen ("Linker"->"System"->"Stack Reserve Size" und "Stack Commit Size"). Oder halt in der Commandline mit "/STACK:reserve,commit".
    Wäre ja auch doof wenn das nicht ginge 😉
    p.S.: interessant ist natürlich hauptsächlich "reserve", weil man will ja nicht gleich 10 oder 100MB committen für den Stack - das wäre Verschwändung.


Log in to reply