Wie ordnet .NET Framework Speicher für OutOfMemoryException zu?

144

In C ++ ist es tatsächlich möglich, eine Ausnahme nach Wert auszulösen, ohne Speicher auf einem Heap zuzuweisen. Daher ist diese Situation sinnvoll. In .NET Framework OutOfMemoryExceptionhandelt es sich jedoch um einen Referenztyp, daher wird er auf einem Heap zugewiesen. Wie ordnet .NET Framework Speicher zu, OutOfMemoryExceptionwenn nicht genügend Speicher zum Erstellen eines neuen Objekts vorhanden ist?

RX_DID_RX
quelle
6
Ausgezeichnete Frage. Vielleicht ist genug Speicher für genau diese Situation reserviert.
GreatAndPowerfulOz
19
Beachten Sie, dass OOM bedeutet, dass der von Ihnen angeforderte Block nicht zugewiesen werden kann, um die anderen Antworten hier bereits zu ergänzen. Wenn Sie nach 100 MB fragen und der größte verfügbare Block, den die Laufzeit finden kann, nur 99 MB ist, schlägt dies fehl. Eine OOM-Ausnahme benötigt jedoch nur wenige Bytes Speicher. Nur weil Ihre Zuordnung fehlgeschlagen ist, bedeutet dies nicht, dass kein Speicher mehr vorhanden ist. Aber natürlich ist es wahrscheinlich, dass die Laufzeit etwas Speicher reserviert, um sich in dieser Situation
Jason Williams
4
Ihre Annahme über C ++ ist übrigens falsch. Abhängig vom Compiler können Ausnahmen auf dem Heap zugewiesen werden. Der MS-Compiler tut dies nicht, aber im Common C ++ ABI werden Ausnahmen auf dem Heap zugewiesen, mit der Ausnahme, dass ein kleiner vorab zugewiesener Notfallpuffer verwendet wird, der stattdessen verwendet wird, wenn auf dem Heap kein Speicherplatz mehr vorhanden ist.
Sebastian Redl

Antworten:

163

Es wird von der Laufzeit vorbelegt. Wenn Sie den Heap eines verwalteten Prozesses untersuchen, finden Sie eine Instanz dieser Ausnahme.

Hier sind die vorab zugewiesenen Ausnahmen einer Hello World-App:

0:003> !dumpheap -stat -type Exception
Statistics:
      MT    Count    TotalSize Class Name
735f2920        1           84 System.ExecutionEngineException
735f28dc        1           84 System.StackOverflowException
735f2898        1           84 System.OutOfMemoryException
735f2744        1           84 System.Exception
735f2964        2          168 System.Threading.ThreadAbortException
Brian Rasmussen
quelle
4
Aber der Konstruktor vonOutOfMemoryException heißt.
Tim Schmelter
36
Die Laufzeit muss nicht nach den gleichen Regeln wie Ihr Code abgespielt werden. Ein anderes Beispiel ist, dass Sie StackOverflowExceptiones abfangen können , wenn Sie werfen , aber wenn die Laufzeit diese Ausnahme auslöst, können Sie es nicht fangen (standardmäßig).
Brian Rasmussen
8
Viele der zugrunde liegenden Mechanismen der CLR sind tatsächlich in "C" und "C ++" geschrieben. Es ist also durchaus möglich, dass das Objekt "neu an Ort und Stelle" ist oder der Speicher anderweitig manipuliert wird.
GreatAndPowerfulOz
2
@hvd Was ist der Nebeneffekt? Gibt OOM eine Stapelverfolgung an? Ich hätte, obwohl der Rest der Informationen ziemlich statisch ist?
James Barrass
7
Was ist, wenn zwei Ausnahmen von Personen mit demselben Typ erforderlich sind, weil zwei Threads sie gleichzeitig auslösen?
Traubenfuchs
42

Wenn innerhalb der Laufzeit ein Speichermangel auftritt , wird ThrowOutOfMemory aufgerufen . Dies ruft Exception :: GetOOMException auf , die das Objekt auf dem Stapel erstellt und es dann in eine statisch zugewiesene globale Instanz kopiert, die dann ausgelöst wird.

Dies ist jedoch nicht die verwaltete Ausnahme, sondern eine in ex.h deklarierte C ++ - Ausnahme . C ++ - Ausnahmen werden in clrex.cpp in verwaltete Ausnahmen konvertiert , die Code zum Auslösen der vorab zugewiesenen verwalteten OutOfMemoryException enthalten, die ursprünglich in appdomain.cpp zugewiesen und erstellt wurde .

Hinweis: Einige dieser Quelldateien sind groß und können Ihren Browser einige Sekunden lang hängen lassen, während die Syntaxhervorhebung geladen wird.

Die Aufrufseiten, die Tim Schmelter in einem Kommentar zur anderen Antwort verlinkt hat, haben nichts mit der Laufzeit zu tun, in der der Speicher knapp wird und kein Objekt erstellt werden kann.

Random832
quelle