C # выдает исключение: как получить стек исключений в IDE? - PullRequest
17 голосов
/ 04 декабря 2010

Ранее здесь обсуждался вопрос о правильном способе отбрасывания исключения. Вместо этого этот вопрос о том, как получить полезное поведение от Visual Studio при использовании rethrow.

Рассмотрим этот код:

   static void foo() {
        throw new Exception("boo!");
    }

    static void Main(string[] args) {
        try {
            foo();
        } catch (Exception x) {
            // do some stuff
            throw;
        }
    }

Возникающее исключение имеет правильную трассировку стека, показывая foo () в качестве источника исключения. Однако , окно GUI Call Stack показывает только Main, тогда как я ожидал, что оно покажет стек вызовов исключения, вплоть до foo.

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

С повторным броском я бы хотел сделать то же самое. Вместо этого стек вызовов, который показывает GUI, бесполезен для меня. Я должен скопировать информацию об исключении в буфер обмена, вставить его в Блокнот, а затем вручную перейти к любой интересующей меня функции стека вызовов.

Кстати, я получаю такое же поведение, если добавляю [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] или меняю улов на просто catch (Exception).

У меня такой вопрос: учитывая, что код, который я использую, использует rethrow, может кто-нибудь предложить удобный способ навигации по стеку вызовов, связанному с исключением? Я использую Visual Studio 2010.

Ответы [ 4 ]

11 голосов
/ 04 декабря 2010

Отладчик прерывается на throw в Main, потому что это исключение не обработано.По умолчанию отладчик будет работать только при необработанных исключениях.Как только вы остановились на Main, стек вызовов для исходного исключения из foo присутствует в исключении, но весь другой контекст был потерян (например, локальные данные, состояние стека / памяти).

Звучит так, будто вы хотите, чтобы отладчик сломался на throw в foo, поэтому вы должны сказать отладчику прерывать на исключениях первого шанса:

  1. Отладка »Исключения ...( Ctrl + Alt + E )
  2. Проверьте «Брошенный» для типов исключений, которые вас интересуют (в данном случае, Commange Language RuntimeИсключения)
  3. Нажмите OK
  4. Начать отладку

В этом случае отладчик немедленно прекратит работу, когда foo сгенерирует исключение.Теперь вы можете проверить стек, локальные объекты и т. Д. В контексте исходного исключения.Если вы продолжите выполнение ( F5 ), отладчик снова прервется при повторном отбрасывании в Main.

При использовании другого подхода, если вы используете VS2010 Ultimate, вы также можете использовать IntelliTrace«отладить в обратном направлении», чтобы увидеть параметры, потоки и переменные во время исключения.См. эту статью MSDN для подробностей.(Полное раскрытие: я работаю в команде, тесно связанной с IntelliTrace).

8 голосов
/ 04 декабря 2010

Если вы используете ReSharper , вы можете скопировать трассировку стека исключений в буфер обмена, а затем выберите в меню: ReSharper> Инструменты> Просмотр трассировки стека (Ctrl + E, T) .Он будет отображать трассировку стека с помощью интерактивных расположений, поэтому вы сможете быстро перемещаться.

http://www.jetbrains.com/resharper/webhelp/images/Reference__Windows__Stack_Trace_Explorer.png

Эта функция также очень полезна при копании журналов пользователей (если в стеке есть исключения)зарегистрированы).

1 голос
/ 04 декабря 2010

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

private static void PreserveStackTrace(Exception exception)
{
  MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
    BindingFlags.Instance | BindingFlags.NonPublic);
  preserveStackTrace.Invoke(exception, null);
}

...
catch (Exception ex)
{
  // do something
  // ...
  PreserveStackTrace(ex);
  throw;
}
0 голосов
/ 28 февраля 2018

Майк Сталл дал отличное и простое решение вашей проблемы:

Отметьте методы, где вы перебрасываете исключение, с атрибутом [DebuggerNonUserCode]

Средапосчитает, что это не ваш код и не сломает отладчик в таком месте, а вместо этого будет искать в стеке следующий повторный вывод или начальное исключение.

(если следующий повторный вызов также раздражаетпометьте его как [DebuggerNonUserCode], и т. д.)

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