Как обрабатывать / ловить StackOverFlowExceptions? - PullRequest
10 голосов
/ 26 августа 2010

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

Я написал код для попытки перехвата исключений StackOverFlowExceptions:

try { recursiveFxn(100000); }
catch(Exception){}
private void recursiveFxn(int countdown)
{
if (countdown > 0)
    recursiveFxn(countdown - 1);
else
    throw new Exception("lol.  Forced exception.");
}

Но все равно я получаю сбои программы (как на NUnit, так и на веб-странице, на которой я работаю). Почему не поймано исключение?

Ответы [ 2 ]

16 голосов
/ 26 августа 2010

Начиная с .NET Framework 2.0, StackOverflowException не может быть перехвачен. Это потому, что это считается плохой практикой. Цитирование документации MSDN :

Начиная с .NET Framework версия 2.0, StackOverflowException объект не может быть пойман при помощи try-catch блок и соответствующий процесс прекращено по умолчанию. Как следствие, пользователям рекомендуется написать свой код обнаружить и предотвратить стек переполнение. Например, если ваш применение зависит от рекурсии, использования счетчик или состояние состояния завершить рекурсивный цикл.

Теперь единственный способ поймать StackOverflowException - это когда он был сгенерирован пользовательским кодом, как объяснено в блоге Джаредом Парсонсом . Кроме этого, с помощью хоста CLR вы можете обрабатывать (но не перехватывать) StackOverflowException и придумывать способ, позволяющий продолжить выполнение вашей программы.

Обратите внимание, что поскольку стек разворачивается при возникновении исключения, в версиях .Net, выпущенных до версии 2.0, при обработке StackOverflowException стек на самом деле будет намного короче, что позволяет делать это без генерации другого StackOverflowException. .

0 голосов
/ 26 августа 2010

Вы не можете поймать исключение переполнения стека, потому что, когда это происходит, это убивает поток мертвым. Try ... catch ... выполняется тем же потоком, чтобы он не работал. Могут быть некоторые API более низкого уровня, которые вы могли бы использовать для P / Invoke и заставить другой поток его перехватить. Также могут быть некоторые API более низкого уровня, чтобы изменить максимальный размер стека, но я не вижу ничего в .NET Framework, чтобы помочь с этим, так что вам снова потребуется P / Invoke что-то.

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