Bezdepbonusu7Программирование: статьи и ответы

Вопрос

StackOverflowException в .NET

Автор вопроса: adamsОтветов: 4

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

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

exception

Ответы

Ответ 1 · рейтинг 18 · blowdart

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

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

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

Ответ 2 · рейтинг 25 · Thomas Danecker

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

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

Самый простой - ThreadAbortException. Когда текущий код выполняется в finally-блоке. ThreadAbortExceptions как бы "перемещены" в конец блока finally. Таким образом, все в блоке finally не может быть прервано исключением ThreadAbortException.

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

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

Есть три формы для выполнения кода в ограниченных областях выполнения (скопированы из Блог команды BCL):

  • ExecuteCodeWithGuaranteedCleanup, безопасная для переполнения стека форма try / finally.
  • Блоку try / finally непосредственно предшествует вызов RuntimeHelpers.PrepareConstrainedRegions. Блок try не ограничен, но есть все блоки catch, finally и fault для этой попытки.
  • As a critical finalizer - any subclass of CriticalFinalizerObject has a finalizer that is eagerly prepared before an instance of the object is allocated.
    • A special case is SafeHandle's ReleaseHandle method, a virtual method that is eagerly prepared before the subclass is allocated, and called from SafeHandle's critical finalizer.

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

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

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

Ответ 3 · рейтинг 1 · Fire Lancer

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

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

Ответ 4 · рейтинг 1 · NBB

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

private Thing _myThing = null;

Public Thing MyThing
{
   get{
        return this.MyThing;}
   set{
        this.MyThing = value;}
}

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы