2009-06-02 13 views
8

Mein PC verfügt über 2 GB RAM-Speicher. Wenn ich ein 3D-Mesh-Objekt mit einem Array von 70.000 Elementen in C# 2008 Express Edition formiere, erhalte ich die Fehlermeldung "Stack Overflow exception handled ...". Wenn ich RAM-Speicher von 2 GB auf 4 GB aufrüste, kann ich diese Fehlermeldung überwinden?Kann ein Upgrade von 2 GB auf 4 GB Stack Overflow-Ausnahmen verhindern?

+10

+1 für einen Stack-Überlauf zu Beispiel versuchen, Frage zu Stack Overflow. Es gab mir das Gekicher. –

+5

Für eine verwandte Frage, siehe hier: stackoverflow.com/questions/941952; -p –

+2

Nur Spaß ... hier (wirklich, diesmal): http://stackoverflow.com/questions/656226/ –

Antwort

11

Nein. Durch Erhöhen des Arbeitsspeichers wird die Stapelgröße nicht erhöht.

Sie schreiben Code, der den Stapelüberlauf verursacht (möglicherweise aufgrund von Rekursion), und Sie müssen das beheben.

+3

In der Tat; unendliche Rekursion ist am wahrscheinlichsten. +1 –

19

Fast sicher nicht. Ein Stack-Überlauf (anstatt zu wenig Arbeitsspeicher) bedeutet, dass Sie den zugewiesenen Stack Speicherplatz verbraucht haben - aber der Stack ist (relativ gesehen) klein. Der Haufen ist, wo alles passiert ...

Optionen:

  • Ihre unendliche Rekursion Fehler zu beheben ...
  • bewegen die Daten in ein Array/Liste/einige Heap-basierten Speicher (wo ist es im Moment?)
  • vermeiden Sie tiefe Rekursion
  • vermeiden Sie übergroße Strukturen ... haben Sie einige große fette Strukturen, die wirklich Klassen sein sollten? (Strukturen kopieren sich selbst, wenn Sie nur blinzeln)
  • erhöhen Sie den Stapelplatz Wenn Sie sind Sie zuversichtlich, dass Sie nur gerade es kippen, und es ist keinen großen Refactor wert (ich hasse diese Antwort) - Dazu müssten Sie Ihren eigenen Thread mit einem größeren Stack spawnen
+0

Hinweis: Diese Antwort könnte so gelesen werden, dass ein Anstieg des physischen RAM die Größe des Heapspeichers erhöht, was nicht der Fall ist. –

+0

Sicher wird es, zumindest auf einem 64-Bit-System? –

+0

Der entscheidende Punkt ist, dass es sehr wenig Einfluss auf den Stack hat - aber (ungeachtet der 2GB/3GB-Grenzen von x86) gibt es immer noch eine Beziehung zwischen physischem RAM und verfügbarem Prozessspeicher. –

2

Wahrscheinlich nicht. Sie sollten increase the stack size, das ist, was die Fehlermeldung sagt

Edit: Oder beheben Sie die unendliche Rekursion, die Sie wahrscheinlich in Ihrem Code haben.

2

Ein Stapelüberlauf kann eine unendliche Rekursion oder eine sehr tief verschachtelte bedeuten.

Zufällig, wenn Sie tail rekursive Methoden haben, wird der x64 JITter sie optimieren und Sie werden überhaupt nicht in Stack-Überläufen laufen (und Ihre unendliche Rekursion wird ... naiv unendlich sein).

So konnte man auf ein 64-Bit OS aktualisieren oder Ihren Code zu beheben, um nicht in dieses Problem zu umgehen (was mehr ist wahrscheinlich ein Fehler als eine zu tief verschachtelte Rekursion ...)

+0

Wie funktioniert das nur auf x64? – SamB

3

Physikalischer Speicher nur Einflüsse Leistung der Programme, die in der Maschine laufen, hat aber nichts mit speicherbedingten Problemen eines Programms zu tun (bei Standard-Betriebssystemen muss das System nach verschiedenen Regeln arbeiten).

Vor allem, weil ich diesen Fehler oft gesehen habe, lassen Sie uns über das Speichermodell des Betriebssystems sprechen.

Fast jedes Benutzer Betriebssystem (ich denke hier an Linux, Windows, BSD, etc) verwendet ein virtuelles Speichermodell. Virtuelles Speichermodell bedeutet, dass jedes Programm vollen Zugriff auf einen privaten virtuellen Speicher erhält, dh eine Darstellung von Speicher, die nicht den entsprechenden physischen Speicher haben müssen.

Die Größe dieses virtuellen Speichers entspricht dem Bereich, der von einem einzelnen Maschinenregister adressiert werden kann. Auf 32-Bit-Betriebssystemen bedeutet das etwa 4 GB. Nun, unabhängig davon, wie viel Speicher Ihr System tatsächlich hat, wird Ihr Programm immer denken, dass er 4 GB hat.

Jetzt werden diese 4GB tatsächlich zwischen Ihrem Programm und dem Speicherplatz aufgeteilt, den das Betriebssystem für die Verarbeitung von Daten im Kernel-Modus reserviert, sowie für die Pflege der von Ihrem Programm benötigten Strukturen. Praktisch können Sie mit etwa 2 oder 3 GB rechnen, abhängig von Ihrer Konfiguration (Ihrer Betriebssystemkonfiguration). All das hat nichts mit der Menge an physischem Speicher zu tun, die Sie haben, Sie können 256 MB RAM haben und Ihr Programm wird immer noch glauben, dass ihm 2 GB zur Verfügung stehen.

Wenn Sie Speicher reservieren, liefert das System normalerweise nicht genau die Menge an Speicher, nach der Sie fragen. Stattdessen werden Seiten verwendet, bei denen es sich um Blöcke reservierten Speichers (z. B. 4 KB) handelt, die für Ihren Prozess zugewiesen sind. Wenn Sie das tun, registriert das Betriebssystem, dass "Seite" wie zugewiesen, aber das ist immer noch im virtuellen Speicher. Intern verwaltet das Betriebssystem, welche dieser Seiten auf dem physikalischen Speicher gehalten werden und welche sich im Austausch befinden (auf der Festplatte). Das ist der Grund, dass die Erhöhung Ihres RAM die Leistung erhöht (mehr Seiten können gleichzeitig im Hauptspeicher sein und Sie müssen weniger von der Festplatte lesen), hilft aber nicht mit einem Stapelüberlauf (oder einer Nicht-Speicher-Ausnahme von der Weg).

Und das warum Erhöhung Ihres RAM wird nicht helfen.

Schließlich, über die Stack Overflow-Ausnahme ... Nun, es ist schwer zu sagen, ohne den tatsächlichen Code zu sehen, wurden einige gute Antworten bereits gegeben.

Meistens Stapelüberlauf kommt von einer unendlichen Rekursion, entweder direkt oder indirekt (A -> B -> C -> A) aber in Ihrem konkreten Fall würde ich sagen, dass Sie nur zu viele Daten in zuweisen der Stapel.

Sie haben ein Array mit 70000 Größe. Ich vermute, dass Array voll von Werttypen ist, die im Stapel zugeordnet sind, die, wenn ich mich richtig erinnere (und bitte nicht das als Tatsache nehmen) 1 MB in .NET ist, was der Grund sein könnte, warum Sie bekommen Ihr Stapelüberlauf.

1

Eigentlich nein. Aber ich habe einen anderen Grund: Windows XP kann nur bis zu 2 GB verarbeiten, wenn Sie in boot.ini keine bestimmte Bootoption angeben. (Der/3gb-Parameter.) Im besten Fall gehen Windows XP und Vista bis zu 3 GB RAM, und das ist im Grunde die Grenze für Windows. Weitere Informationen zu diesen Grenzwerten finden Sie unter This link.

Wenn Sie Ihren RAM-Speicher erhöhen und Ihre Anwendung so reparieren, dass sie die Grenze von 2 GB überschreitet, kann dies zu einem Überlauf des Stacks führen, da der Stack dadurch möglicherweise vergrößert wird. Es könnte auch den Moment dieses Stack-Überlaufs verzögern, da sich Ihr Code, wie vorgeschlagen, in einer endlosen rekursiven Schleife befindet und so lange weiterläuft, bis keine Ressourcen mehr verfügbar sind.

Wenn Sie Rekursion verwenden, sollten Sie Folgendes beachten: Alles, was Sie mithilfe der Rekursion tun, kann ohne Rekursion neu geschrieben werden. Es gibt keine Ausnahmen von dieser Regel, obwohl der Code nicht einfacher zu lesen ist.

+1

Tatsächlich ändert das Flag/3Gb die maximale Menge pro Prozessspeicher, die zugewiesen werden kann. Windows XP und Vista werden beide glücklich 4 GB RAM nehmen, aber nur Zugriff auf ca. 3.5 GB davon erlauben, wobei die verbleibenden 500 MB adressierbaren Speicherplatz für anderen Speicher wie Grafikkarten usw. verwendet werden. –

+0

Wahr, aber aus der Perspektive der Anwendung Die Anwendung ist weiterhin auf 3 GB begrenzt. Das Upgrade auf 4 GB bedeutet weniger Swapping, aber nicht mehr Speicher für Ihren Prozess. –

0

ich nicht für C# wissen, aber in Java, bedeuten Stackoverflow-Fehler, dass Sie Instanz einer Klasse in der Klasse erstellen, die in der Klasse bereits instanziert wurden Sie

Verwandte Themen