2015-10-30 3 views
139

В C++ на самом деле можно выбросить исключение по значению без выделения памяти в кучу, поэтому такая ситуация имеет смысл. Но в .NET framework OutOfMemoryException является ссылочным типом, поэтому он выделяется в кучу. Как платформа .NET выделяет память для OutOfMemoryException, когда памяти недостаточно для создания нового объекта?Как платформа .NET выделяет память для OutOfMemoryException?

+5

Отличный вопрос. Возможно, достаточно памяти зарезервировано именно для этой ситуации. – GreatAndPowerfulOz

+18

Чтобы добавить к другим ответам уже здесь, имейте в виду, что OOM означает, что запрошенный вами блок не может быть выделен. Если вы попросите 100Mb и самый большой доступный блок, который может найти время выполнения, это всего лишь 99Mb, он будет терпеть неудачу. Но для исключения OOM требуется только несколько байтов памяти. Так что только потому, что ваше распределение не удалось, это не значит, что осталось нулевое количество памяти. Но, конечно, вполне вероятно, что время выполнения резервирует некоторую память, чтобы покрыть себя в этой ситуации. –

+3

Ваше предположение о C++, кстати, неверно. В зависимости от компилятора исключения могут быть выделены в куче. Компилятор MS не работает, но в Common C++ ABI исключения выделяются в куче, за исключением того, что имеется небольшой предварительно выделенный буфер аварийной ситуации, который будет использоваться вместо этого, если в куче нет места. –

ответ

155

Он предопределен временем выполнения. Если вы исследуете кучу любого управляемого процесса, вы найдете экземпляр этого исключения.

Вот предопределенные исключения в приложение 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 
+3

Но вызывается [конструктор 'OutOfMemoryException'] (http://referencesource.microsoft.com/#mscorlib/system/outofmemoryexception.cs,5ad855b434264d4b.references). –

+0

Извините, я не уверен, что вы думаете. –

+35

Время выполнения не должно воспроизводиться по тем же правилам, что и ваш код. Другим примером является то, что если вы бросаете 'StackOverflowException', вы можете его поймать, но если runtime выбрасывает это исключение, вы не можете его поймать (по умолчанию). –

39

Когда состояние вне памяти встречается в среде выполнения, он вызывает ThrowOutOfMemory. Это вызывает Exception::GetOOMException, который строит объект в стеке и затем копирует его в статически назначенный глобальный экземпляр, который затем бросается.

Это не управляемое исключение, но это исключение C++, указанное в ex.h. Исключения C++ преобразуются в управляемые исключения в clrex.cpp, в котором содержится код, специально предназначенный для выброса предопределенного OutOfMemoryException, которое изначально было выделено и построено в appdomain.cpp.

Примечание. Некоторые из этих исходных файлов большие и могут зависеть от вашего браузера в течение нескольких секунд, пока он загружает подсветку синтаксиса.

Сайты вызовов, которые Тим Шмельтер связал в комментарии к другому ответу, не связаны с тем, что время выполнения заканчивается из памяти и неспособно построить объект.