StackOverflowException в .NET - PullRequest
       20

StackOverflowException в .NET

13 голосов
/ 20 сентября 2008

После нажатия нескольких исключений StackOverflowException в .NET я заметил, что они полностью обходят необработанные обработчики исключений, которые предлагает .NET (Application.ThreadException / AppDomain.UnhandledException). Это очень тревожно, так как у нас есть критический код очистки в этих обработчиках исключений.

Есть ли способ преодолеть это?

Ответы [ 4 ]

25 голосов
/ 20 сентября 2008

Существует три вида так называемых «асинхронных исключений». Это исключение ThreadAbortException, OutOfMemoryException и упомянутое StackOverflowException. Эти исключения разрешены в любой инструкции вашего кода.

И есть также способ преодолеть их:

Самым простым является исключение ThreadAbortException. Когда текущий код выполняется в блоке finally. Исключения ThreadAbortException как бы «перемещаются» в конец блока finally. Поэтому все в блоке finally не может быть прервано исключением ThreadAbortException.

Чтобы избежать исключения OutOfMemoryException, у вас есть только одна возможность: ничего не размещать в куче. Это означает, что вам не разрешено создавать какие-либо новые ссылочные типы.

Чтобы преодолеть исключение StackOverflowException, вам нужна помощь со стороны Framework. Эта помощь проявляется в регионах с ограниченным исполнением. Требуемый стек выделяется за до фактического выполнения кода, а также дополнительно гарантирует, что код уже JIT-скомпилирован и поэтому доступен для исполнения.

Существует три формы для выполнения кода в ограниченных областях выполнения (скопировано из BCL Team Blog ):

  • ExecuteCodeWithGuaranteedCleanup, безопасная форма переполнения стека для try / finally.
  • Блок try / finally, которому сразу предшествует вызов RuntimeHelpers.PrepareConstrainedRegions. Блок try не ограничен, но все блоки catch, finally и fault для этой попытки:
  • В качестве критического финализатора - любой подкласс CriticalFinalizerObject имеет финализатор, который охотно готовится до того, как будет выделен экземпляр объекта.
    • Особый случай - метод ReleaseHandle SafeHandle, виртуальный метод, который охотно готовится до выделения подкласса и вызывается из критического финализатора SafeHandle.

Вы можете найти больше в этих сообщениях в блоге:

Области ограниченного исполнения и другие ошибки [Брайан Грюнкемейер] в блоге команды BCL.

Интернет-журнал Джо Даффи о Атомарности и ошибках асинхронных исключений , где он дает очень хороший обзор асинхронных исключений и надежности в .net Framework.

18 голосов
/ 20 сентября 2008

Не совсем; переполнение стека или исключение нехватки памяти в самой CLR означает, что что-то пошло не так (я обычно получаю это, когда я тупица и создаю рекурсивное свойство).

Когда возникает это состояние, CLR не может выделить новые вызовы функций или память, чтобы он мог вызывать обработчики исключений; это сценарий «мы должны остановить сейчас ».

Если, однако, вы сами выбросите исключение, ваши обработчики исключений будут вызваны.

1 голос
/ 01 июня 2010

Удар прибил его, выше. Dumbass рекурсивное свойство, как он любит это называть. На самом деле просто проблема с набором кода слишком быстро.

private Thing _myThing = null;

Public Thing MyThing
{
   get{
        return this.MyThing;}
   set{
        this.MyThing = value;}
}
1 голос
/ 20 сентября 2008

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

Единственное, что вы действительно можете сделать, это отследить причину и вообще предотвратить ее возникновение (например, быть осторожным с рекурсией и не размещать большие объекты в стеке).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...