Ich arbeite mit C#.NET 2003 Standard.
Der Stackspeicher ist von Anfang auf 1MB eingestellet.
Wie kann ich ihn erhoehen?
Hallo GeorgSchelkle,
ich weiß nicht, wie es bei 1.1 ist, aber bei 2.0 wächst der Stackspeicher m.E. automatisch mit.
herbivore
Komt drauf an, was du machen willst. Abweichend vom Default-Wert kannst du in 2.0 (XP SP2 bzw. 2003 vorrausgesetzt) jedem Thread gezielt eine Thread-Größe mitgeben (Konstruktor).
Der Default-Wert kann für fertige Anwendungen mittels editbin /stack nachträglich verändert werden. Das geht auch mit 1.1.
Aus reiner neugir oder Unwissenheit, je nach dem wie man es sehen will. Für was ist das gut, bzw. was ist der Nutzen. oder allgem. für was braucht ein Thread Speicher?
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Hallo kleines_eichhoernchen,
auf dem Stack werden die Parameter und lokalen Methoden sowie die Return-Adressen der Methodenaufrufe abgelegt. Wenn man rekursive Programm schreibt, braucht man u.U. sehr viel Stack-Speicher. Da jeder Thread eben ein eigener Faden der Programmausführung, in dem Methodenaufrufe stattfinden ist, braucht jeder Speicher seinen eigenen Stack.
herbivore
Deshalb auch die "lustige" Meldung, wenn man die Funktion in der man gerade ist immer wieder selbst aufruft🙂
Wie oft kann die Methode aufgerufen werden? im schnitt bei Standardeinstellung?
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Hallo kleines_eichhoernchen,
das hängt davon ab, wieviele Parameter und lokale Variablen die Methode hat bzw. wieviel Platz Parameter und lokale Variablen belegen. Eine Referenzvariable (class) benötigt unter 32bit 4 Byte aber eine Valuevariable (struct) benötigt für alle enthaltenen Member Platz. Dazu kommen 4 Byte für die Rücksprungadresse. Jetzt kannst du ausrechnen (oder ausprobieren), wieviele Aufrufe in 1 MB möglich sin-
herbivore
Kleine Korrektur: Eine Referenz benötigt unter .NET 12 Bytes.
Ich habe versucht den Stapel-Speicher für eine ausführbare Datei
mit EDITBIN zu vergrössern. Hat nicht geklappt. Kann mir jemand
ein Beispiel machen.
Ist folgendes richtig :
EDITBIN /STACK: 10000000 c:\Projekte\TestProgramm.exe
Nocheinmal, Wozu?
Und EDITBIN ist definitiv der Falsche Weg, denn es ist für COFF Dateien.
Original von FZelle
Und EDITBIN ist definitiv der Falsche Weg, denn es ist für COFF Dateien.
CLR-Anwendungen sind erweitertes COFF.
EDITBIN /STACK: 10000000 c:\Projekte\TestProgramm.exe
Wenn da ein Leerzeichen zwischen STACK und 1000000 ist, dann wird das der Grund sein.
Wofür braucht man eigentlich einen STACK im MB-Bereich?
Quicksort nach Farbe bei irgendwelchen lokalen Arrays?
Mir sind Überschreitungen von 64 KB sonst schon peinlich.. 😉
Ne im Ernst: Wozu? Sieht nach Rekursion aus - wo sie nichts mehr zu suchen hat.
Die Frage ist allerdings berechtigt. Die Stacksize zu erhöhen ist auf jeden Fall kein Weg einen Stackoverflow durch Endlosrekursion loszuwerden.
*EDIT*
Editbin.exe nochmal getestet. Funktioniert tadellos.
Ich arbeite u.a. mit Visual C++ 6.0 Professional.
Auch hier hätte ich gern den Stack-Speicher erhoeht.
(Projekte, Einstellungen, Linker, Ausgabe, Reservieren )
klappt nicht. Kann man EDITBIN verwenden, und wie ?
Was sind Moduldefinitionsdateien, und wie geht man mit ihnen
um ? Dies ist zwar keine C#-Themen, vielleicht weiss doch jemand Rat.
Hallo GeorgSchelkle,
ich habe deine Frage mal hier angefügt, weil es bestimmt in mancherlei Hinsicht egal ist, mit welcher Programmiersprache man arbeitet, z.B. bei der Frage "Wofür braucht man eigentlich einen STACK im MB-Bereich?", die du ja noch nicht beantwortet hast. 🙂
herbivore
Du kannst über die Compiler Option /F[ ]number die Stackgröße bestimmen. Wenn sich VS weigert, einfach bei den zusätzlichen Kommandozeilenargumenten angeben.
Bei den Antworten auf meine Frage "Wie kann ich den Stack-Speicher
erhoehen" kam mermals die Frage; wozu ?
Ich habe einen Lisp-Interpretierer ( GLisp ) in VC++ 6.0 geschrieben.
Also eine eigene Programmiersprache programmiert ( wenn auch nur einen
Dialekt ). Bei GLisp ist es üblich das man rekursiv programmiert. Damit man
auch grössere Daten ( Listen ) verarbeiten kann, muss die Rekursionstiefe
ausreichend hoch sein. Ich habe die Idee von VC++ 6.0 auf C# zu portieren.
Wenn es dein eigener Interpreter ist, kannst du doch die Rekursion beim interpretieren in eine Iteration überführen.
Dazu kannst du in einem Stack<T> den Aufrufstack des interpretierten Programms speichern. Damit ist die Rekursionstiefe des interpretierten Codes nur durch den Arbeitsspeicher begrenzt.
Anders auch gar nicht möglich. Anders als in C++ kann man ja keine Objekte auf den Stack legen. Jede Collection wird zum Heap-Objekt.
Ich wollte damit nur ausdrücken, dass man die Rekursion in der interpretierten Sprache nicht als Rekursion in der interpretierenden Sprache ausführen muss.
Original von Borg
Dazu kannst du in einem Stack<T> den Aufrufstack des interpretierten Programms speichern. Damit ist die Rekursionstiefe des interpretierten Codes nur durch den Arbeitsspeicher begrenzt.
Kannst du zu dieser Verwendung mal nen kleines Beispiel geben bitte?`Bin neugirig😉
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Hallo GeorgSchelkle,
gerade in Lisp ist es üblich, durch den Interpreter/Compiler endrekursive Funktionen automatisch in Iterationen umzuwandeln, weshalb auch bei den Entwicklung von Lisp-Programmen angestrebt wird/werden sollte wo immer möglich, endrekursiv zu Programmieren.
Außerdem sind durch dir Einführung von iterativen Konstrukten (z.B. do) in Lisp möglich und sinnvoll, Iterationen auch als solche Auszudrücken.
Zusammengenommen sollte der Stack-Bedarf eines Lisp Programms nicht wesentlich höher sein als der eines C# Programms.
Hallo kleines_eichhoernchen,
was willst du denn da für ein Beispiel haben? Einfach beim Funktionsaufruf mit Push die Parameter und/oder den Rückkehrpunkt auf den Stack packen und beim Verlassen mit Pop wieder abräumen. Und wenn du sehen willst, wie das in Code aussieht, dann guckst du in die Code-Beispiele in der MSDN.
herbivore
Hallo kleines_eichhörnchen !
Das folgende GLisp-Beispiel ist trivial, es berechnet die Summe der Zahlen
in einer Liste:
<DEFUN Summe <L>
{ COND { <NULL? L> 0 }
{ #t { + <CARL> <Summe <CDR L>> } } } >;
Wenn der Funktion eine Zahlen-Liste mit einer Länge von mehr als
500000 Zahlen übergeben wird, braucht man eine grosse Rekursionstiefe.
Entschuldigung wegen der Trivialität ! Dies kann man natürliche auch
iterativ schreiben ( stimmt ).
Ihr könnt mich ja fragen warum ich GLisp programmiert habe.
Seit langem habe ich die Idee, das Programmieren einfacher zu machen.
Dann bin ich auf die Idee gekommen ein Optimierungsprogramm zu
entwickeln. Das hätte dann den Vorteil, dass man beim Software-Entwickeln
nicht mehr auf Effizienz achten muss. Die funktionale Sprache GLisp
hat den Vorteil dass Programme und Daten die gleiche Gestalt haben, nämlich
Listen sind. Ausserdem ist GLisp eine Sprache für Künstliche-Intelligenz, was
mich auch interessiert.
Hallo GeorgSchelkle,
Dies kann man natürliche auch iterativ schreiben ( stimmt ).
nicht nur das. Der Interpreter kann und sollte das intern automatisch in eine Interation umwandeln.
herbivore
Warum sollte ein Interpreter das tun?
Falls er das tut: ist es der falsche Interpreter(Syntax ist dafür da den Interpreter zu steuern).
Hallo ikaros,
Warum sollte ein Interpreter das tun?
aus Optimierungsgründen. Solange sich die Semantik sich nicht ändert, kann der Interpreter intern umstellen, was er will.
Falls er das tut: ist es der falsche Interpreter
Wenn du damit recht hättest - was du nicht hast - dann wären die meisten existierenden Lisp-Interpreter fasch.
herbivore
Hallo,
ist es möglich eine StackOverflowException auch ab dem .NET Framework 2.0 zu fangen? Ziel ist es in einem Testprojekt die Rekursionstiefe zu testen, ohne das das komplette Programm abschmiert (Anregung durch den Thread Frage zum Auslesen eines Binärbaumes
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Du kannst sie versuchen zu fangen, aber das Problem ist, dass nicht garantiert ist, dass das Programm anschließend weiterläuft. Auf keinen Fall solltest du innerhalb des Catch-Blocks irgendeine Methode ausführen. Also am besten einen leeren Block.
Hallo svenson,
ich meine, mich dunkel zu erinnern, dass für die Behandlung einer StackOverflowException extra ein paar Bytes auf dem Stack reserviert sind. Aber ich will auch kein Gerücht in die Welt setzen. Ich weiß nicht mehr, wo ich das herhabe und ob ich mich irre.
Hallo kleines_eichhoernchen,
eine StackOverflowException ist auf jeden Fall eine blöde/unangenehme Exception, die man vermeiden sollte, z.B. dadurch, dass man durch Programmierung selbst die Rekursionstiefe begrenzt.
herbivore
Seit 2.0 ist wohl Essig mit fangen:
In prior versions of the .NET Framework, your application could catch a StackOverflowException object (for example, to recover from unbounded recursion). However, that practice is currently discouraged because significant additional code is required to reliably catch a stack overflow exception and continue program execution.
Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default.
In 1.1 war es schlicht Zufall, ob man die Exception fangen konnte oder nicht, je nachdem wo die StackOverflow-Exception auftrat. War es eine Methodencall außerhalb des Frameworks konnte fangen, war es innerhalb der VM dann war Essig.
Das bis .NET 1.1 es möglich ist, die StackoverflowException zu fangen, hab ich gestern auch gelesen. Ich hab mir gedacht mittels eines speziellen Attributes oder Compiler-Option ist dies dennoch ab 2.0 möglich.
Noch eine Frage,
corresponding process is terminated by default.
ist damit der komplette Process gemeint oder die aktuelle AppDomain?
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...