Bagaimana .NET framework mengalokasikan memori untuk OutOfMemoryException?

144

Dalam C ++ sebenarnya mungkin untuk melempar pengecualian dengan nilai tanpa mengalokasikan memori pada tumpukan, jadi situasi ini masuk akal. Tetapi dalam .NET framework OutOfMemoryExceptionadalah tipe referensi, oleh karena itu dialokasikan pada heap. Bagaimana .NET framework mengalokasikan memori OutOfMemoryExceptionketika tidak ada cukup memori untuk membuat objek baru?

RX_DID_RX
sumber
6
Pertanyaan yang sangat bagus Mungkin cukup memori dicadangkan hanya untuk situasi itu.
GreatAndPowerfulOz
19
Hanya untuk menambahkan jawaban lain yang sudah ada di sini, ingatlah bahwa OOM berarti bahwa blok yang Anda minta tidak dapat dialokasikan. Jika Anda meminta 100Mb dan blok terbesar yang dapat ditemukan runtime hanya 99Mb, itu akan gagal. Tetapi pengecualian OOM hanya membutuhkan beberapa byte memori. Jadi hanya karena alokasi Anda gagal, itu tidak berarti ada memori yang tersisa. Tapi tentu saja ada kemungkinan runtime menyimpan sebagian memori untuk menutupi dirinya sendiri dalam situasi ini
Jason Williams
4
Omong-omong, asumsi Anda tentang C ++ salah. Bergantung pada kompiler, pengecualian mungkin dialokasikan pada heap. Kompiler MS tidak, tetapi dalam Common C ++ ABI, pengecualian dialokasikan pada heap, kecuali bahwa ada buffer darurat kecil yang telah dialokasikan sebelumnya yang akan digunakan sebagai gantinya jika tidak ada ruang tersisa di heap.
Sebastian Redl

Jawaban:

163

Ini dialokasikan oleh runtime. Jika Anda menjelajahi tumpukan proses yang dikelola, Anda akan menemukan contoh pengecualian itu.

Berikut adalah pengecualian yang telah dialokasikan sebelumnya dari aplikasi 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
Brian Rasmussen
sumber
4
Tetapi konstruktorOutOfMemoryException disebut.
Tim Schmelter
36
Runtime tidak harus dimainkan dengan aturan yang sama dengan kode Anda. Contoh lain adalah bahwa jika Anda melempar, StackOverflowExceptionAnda dapat menangkapnya, tetapi jika runtime melempar pengecualian itu, Anda tidak dapat menangkapnya (secara default).
Brian Rasmussen
8
Banyak mekanisme yang mendasari CLR sebenarnya ditulis dalam "C" dan "C ++". Jadi, sangat mungkin bahwa objek "baru di tempat" atau memori dimanipulasi.
GreatAndPowerfulOz
2
@ hvd Apa efek sampingnya? Apakah OOM memberikan jejak stack? Saya akan memiliki sisa informasi yang cukup statis?
James Barrass
7
Bagaimana jika dua pengecualian dari mereka yang memiliki jenis yang sama diperlukan karena dua utas melemparkannya pada saat yang sama?
Traubenfuchs
42

Ketika kondisi kehabisan memori ditemukan di dalam runtime, ia memanggil ThrowOutOfMemory . Ini memanggil Exception :: GetOOMException , yang membuat objek pada stack dan kemudian menyalinnya ke instance global yang dialokasikan secara statis, yang kemudian dibuang.

Namun, ini bukan Pengecualian yang dikelola, ini merupakan pengecualian C ++ yang dinyatakan dalam ex.h . C ++ Pengecualian dikonversi ke Pengecualian terkelola di clrex.cpp , yang berisi kode untuk secara khusus membuang OutOfMemoryException terkelola yang dialokasikan sebelumnya, yang awalnya dialokasikan dan dibuat di appdomain.cpp .

Catatan: Beberapa file sumber ini berukuran besar dan dapat menggantung browser Anda selama beberapa detik saat memuat highlight sintaksis.

Situs panggilan yang ditautkan oleh Tim Schmelter dalam komentar pada jawaban lain tidak terkait dengan runtime kehabisan memori dan tidak dapat membangun objek.

Random832
sumber