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.