С# - Как обрабатывать/захватывать StackOverFlowExceptions?

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

Я написал код, чтобы попытаться поймать 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, так и на веб-странице, которую я запускаю). Почему исключение не исключено?

Ответ 1

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

Начиная с .NET Framework версия 2.0, a StackOverflowExceptionобъект не может быть захвачен попыткой блок и соответствующий процесс завершено по умолчанию. Вследствие этого, пользователям рекомендуется написать свой код для обнаружения и предотвращения стека переполнение. Например, если ваш приложение зависит от рекурсии, использования счетчиком или условием состояния завершите рекурсивный цикл.

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

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

Ответ 2

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