С# поймать исключение

Я получил рекурсивный вызов методу, который генерирует исключение. Первый вызов окружен блоком catch try, но исключение не попадает.

Выполняет ли исключение особым образом? Могу ли я правильно поймать/обработать исключение?

Примечание: если необходимо:

  • исключение не выбрасывается в основной поток

  • объект, в котором код генерирует исключение, вручную загружается Assembly.LoadFrom(...). CreateInstance (...)

Ответ 1

Начиная с 2.0, исключение StackOverflow можно обнаружить только в следующих обстоятельствах.

  • CLR запускается в размещенной среде, где хост специально разрешает обработку исключений StackOverflow
  • Исключение stackoverflow генерируется кодом пользователя, а не из-за реальной ситуации (Ссылка)

Ответ 2

Правильный способ - исправить переполнение, но....

Вы можете дать себе больший стек: -

using System.Threading;
Thread T = new Thread(threadDelegate, stackSizeInBytes);
T.Start();

Вы можете использовать свойство System.Diagnostics.StackTrace FrameCount, чтобы подсчитать используемые вами кадры и выбросить свое собственное исключение, когда достигнут предел рамки.

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

class Program
{
    static int n;
    static int topOfStack;
    const int stackSize = 1000000; // Default?

    // The func is 76 bytes, but we need space to unwind the exception.
    const int spaceRequired = 18*1024; 

    unsafe static void Main(string[] args)
    {
        int var;
        topOfStack = (int)&var;

        n=0;
        recurse();
    }

    unsafe static void recurse()
    {
        int remaining;
        remaining = stackSize - (topOfStack - (int)&remaining);
        if (remaining < spaceRequired)
            throw new Exception("Cheese");
        n++;
        recurse();
    }
}

Просто поймай Сыра.;)

Ответ 3

На странице MSDN на StackOverflowException s:

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

Начиная с .NET Framework версия 2.0, исключение StackOverflowException объект не может быть захвачен попыткой блок и соответствующий процесс завершено по умолчанию. Вследствие этого, пользователям рекомендуется написать свой код для обнаружения и предотвращения стека переполнение. Например, если ваш приложение зависит от рекурсии, использования счетчиком или условием состояния завершите рекурсивный цикл. Заметка что приложение, в котором размещены общая среда выполнения CLR укажите, что CLR выгружает область приложения, в которой стек исключение переполнения, и соответствующий процесс продолжается. Для больше информации, см. Интерфейс ICLRPolicyManager и Хостинг Common Language Runtime.

Ответ 4

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

Для этого вам нужно открыть "Настройки исключения" в меню "Отладка". В старых версиях Visual Studio это "Debug" - "Exceptions"; в новых версиях он находится в 'Debug' - 'Windows' - 'Exception Settings'.

После того, как у вас откроются настройки, разверните "Исключения общего времени выполнения языка", разверните "Система", прокрутите вниз и отметьте "Исправление System.StackOverflowException". Затем вы можете посмотреть стек вызовов и искать повторяющийся шаблон вызовов. Это должно дать вам представление о том, где искать исправление кода, вызывающего переполнение стека.

Ответ 5

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

http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx

Начиная с .NET Framework версии 4, это событие не возникает для исключений, которые повреждают состояние процесса, например переполнение стека или нарушения доступа, если обработчик событий не критичен с точки зрения безопасности и имеет атрибут HandleProcessCorruptedStateExceptionsAttribute.

Тем не менее, ваше приложение прекратится после выхода из функции event (ОЧЕНЬ грязное обходное решение, должно было перезапустить приложение в этом событии haha, havn't сделано так и никогда не будет делать). Но это достаточно хорошо для регистрации!

В версиях .NET Framework версии 1.0 и 1.1 необработанное исключение, которое встречается в потоке, отличном от основного потока приложений, улавливается средой выполнения и, следовательно, не приводит к завершению приложения. Таким образом, событие UnhandledException может быть поднято без завершения приложения. Начиная с версии .NET Framework версии 2.0, этот блокиратор обратных ссылок для необработанных исключений в дочерних потоках был удален, поскольку кумулятивный эффект таких молчащих сбоев включал снижение производительности, поврежденные данные и блокировки, все из которых были трудно отлаживать. Для получения дополнительной информации, включая список случаев, в которых среда выполнения не завершена, см. Исключения в управляемых потоках.

Ответ 7

Вы не можете. CLR не позволит вам. Переполнение стека является фатальной ошибкой и не может быть восстановлено.

Ответ 8

Вы не можете, как объясняет большинство сообщений, позвольте мне добавить еще одну область:

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

Ответ 9

Это невозможно, и по уважительной причине (например, подумайте обо всех этих catch (Exception) {}).

Если вы хотите продолжить выполнение после, запустите опасный код в другом AppDomain. Политики CLR могут быть установлены так, чтобы прервать текущий AppDomain при переполнении без ущерба для исходного домена.