In che modo .NET framework alloca memoria per OutOfMemoryException?


144

In C ++ è effettivamente possibile generare un'eccezione in base al valore senza allocare memoria su un heap, quindi questa situazione ha senso. Ma in .NET framework OutOfMemoryExceptionè un tipo di riferimento, quindi è allocato su un heap. In che modo .NET framework alloca memoria per OutOfMemoryExceptionquando non c'è memoria sufficiente per creare un nuovo oggetto?


6
Ottima domanda Forse abbastanza memoria è riservata solo a quella situazione.
GreatAndPowerfulOz

19
Solo per aggiungere alle altre risposte già qui, tenere presente che OOM significa che il blocco richiesto non può essere assegnato. Se si richiedono 100 Mb e il blocco disponibile più grande che il runtime è in grado di trovare è solo 99 Mb, fallirà. Ma un'eccezione OOM richiede solo pochi byte di memoria. Quindi, solo perché l'allocazione non è riuscita, ciò non significa che rimanga zero memoria. Ma ovviamente è probabile che l'autonomia si riservi un po 'di memoria per coprirsi in questa situazione
Jason Williams,

4
A proposito, la tua ipotesi sul C ++ non è corretta. A seconda del compilatore, le eccezioni potrebbero essere allocate sull'heap. Il compilatore MS non lo fa, ma nell'ABI C ++ comune, le eccezioni sono allocate sull'heap, tranne per il fatto che esiste un piccolo buffer di emergenza preallocato che verrà utilizzato se non c'è spazio sull'heap.
Sebastian Redl,

Risposte:


163

Viene preallocato dal runtime. Se esplori l'heap di qualsiasi processo gestito troverai un'istanza di tale eccezione.

Ecco le eccezioni preallocate di un'app Hello World:

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


36
Il runtime non deve giocare secondo le stesse regole del tuo codice. Un altro esempio è che se lo lanci StackOverflowExceptionpuoi catturarlo, ma se il runtime genera quell'eccezione non puoi catturarlo (per impostazione predefinita).
Brian Rasmussen,

8
Gran parte dei meccanismi sottostanti del CLR sono in realtà scritti in "C" e "C ++". Quindi, è del tutto possibile che l'oggetto sia "nuovo in posizione" o che la memoria sia altrimenti manipolata.
GreatAndPowerfulOz

2
@hvd Qual è l'effetto collaterale? OOM fornisce una traccia dello stack? Avrei pensato che il resto delle informazioni fosse abbastanza statico?
James Barrass,

7
Cosa succede se sono necessarie due eccezioni di quelle con lo stesso tipo perché due thread le lanciano contemporaneamente?
Traubenfuchs,

42

Quando si verifica una condizione di memoria insufficiente all'interno del runtime, chiama ThrowOutOfMemory . Questo chiama Exception :: GetOOMException , che costruisce l'oggetto nello stack e quindi lo copia in un'istanza globale allocata staticamente, che viene quindi lanciata.

Questo non è l'eccezione gestita, però, è un'eccezione C ++ dichiarato nel ex.h . Le eccezioni C ++ vengono convertite in eccezioni gestite in clrex.cpp , che contiene il codice per lanciare in modo specifico OutOfMemoryException gestita preallocata , originariamente allocata e costruita in appdomain.cpp .

Nota: alcuni di questi file di origine sono di grandi dimensioni e potrebbero bloccare il browser per alcuni secondi mentre carica l'evidenziazione della sintassi.

I siti di chiamata che Tim Schmelter ha collegato in un commento sull'altra risposta non sono correlati al tempo di esecuzione della memoria in esaurimento e all'incapacità di costruire un oggetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.