Комментарии 9
Всё достаточно просто: выражение throw; в C# теряет стек исключения (вернее, просто генерирует его заново).throw; ничего не теряет. Вот если сделать throw e; где e — пойманное исключение, тогда да, стек заменится.
+7
Вообще говоря, здесь я действительно промахнулся, т.к. был введён в заблуждение собственными примерами. Стек при
Текст статьи исправлен.
throw;
всё же немного модифицируется, но в нём меняется только номер строки в пределах той функции, где было поймано исключение.Текст статьи исправлен.
0
Эм. Запустил вот такой код:
Условие e.StackTrace == _originalStrace выполняется, т. е. стектрейс никак не модифицируется
static string _originalStrace;
static void Throw ()
{
throw new Exception ();
}
static void ThrowAndRethrow ()
{
try {
Throw ();
} catch (Exception e) {
_originalStrace = e.StackTrace;
throw;
}
}
public static void Main (string[] args)
{
try {
ThrowAndRethrow ();
} catch (Exception e) {
Console.WriteLine (e.StackTrace == _originalStrace);
}
}
Условие e.StackTrace == _originalStrace выполняется, т. е. стектрейс никак не модифицируется
0
Вы удивитесь, но у меня он выводит False. VS2012, .NET4.5.
0
Занятно. На Mono true. Видимо, отличия реализаций CLR всё же сказываются даже на таком уровне. Причём .NET ещё и в _originalStackTrace забывает положить информацию о том, что вызов был из Main, в трейсе только два кадра стека.
0
Проверил, что именно там происходит. Вот два стека, которые генерируются в процессе работы вашей программы:
Помимо разной глубины стеков (ну, это уж точно артефакт несоответствия mono и .NET), видно, что строки действительно разные.
at CSharpFilter.Program.Throw() in CSharpFilter\Program.cs:line 40 // throw new Exception();
at CSharpFilter.Program.ThrowAndRethrow() in CSharpFilter\Program.cs:line 46 // Throw();
at CSharpFilter.Program.Throw() in CSharpFilter\Program.cs:line 40 // throw new Exception();
at CSharpFilter.Program.ThrowAndRethrow() in CSharpFilter\Program.cs:line 52 // throw;
at CSharpFilter.Program.Main(String[] args) in CSharpFilter\Program.cs:line 59 // ThrowAndRethrow();
Помимо разной глубины стеков (ну, это уж точно артефакт несоответствия mono и .NET), видно, что строки действительно разные.
0
Один из разработчиков Microsoft Roslyn (@KirillOsenkov) недавно рассказывал, что они используют exception filters внутри тестов для одной интересной задачи — автоматического снятие минидампа процесса до непосредственно разворачивания стека при возникновении исключения.
Хотел написать такой же хелпер (если DynamicMethod позволяет делать
Еще вроде в статье не упомянуто, что в случае возникновения исключения в filter-блоке, это равнозначно значению 0 на стеке по окончанию исполнения фильтра (то есть предикат фильтрации считается вернувшим false), а само исключение безвозвратно теряется.
В dotPeek не сделано ввиду исключительной редкости данной конструкции, постраюсь запилить на следующую версию ;)
Хотел написать такой же хелпер (если DynamicMethod позволяет делать
BeginExceptFilterBlock
, конечно, в чем я сомневаюсь), что-нибудь типа MiniDump.Execute(() => { ... })
в топ левеле и чтобы процесс сам себя дампил, да дампами не пользуюсь вообще (процессы слишком жирные).Еще вроде в статье не упомянуто, что в случае возникновения исключения в filter-блоке, это равнозначно значению 0 на стеке по окончанию исполнения фильтра (то есть предикат фильтрации считается вернувшим false), а само исключение безвозвратно теряется.
В dotPeek не сделано ввиду исключительной редкости данной конструкции, постраюсь запилить на следующую версию ;)
+6
Спасибо за пояснения. А вот вопрос исключений внутри фильтра я попробую на досуге изучить подробнее — тема интересная. Например, что будет, если в фильтре выпадет что-нибудь ужасное, типа StackOverflow или OutOfMemory? А если из нативного кода пробросить? Если где-то и искать баги рантайма, то именно в таких, редко возникающих кейсах.
0
throw теряет оригинальный стек — на .NET 2.0 — 3.5 подтверждаю.
PS ну где была эта статья, когда мы писали сложные синхронные приложения?..
PS ну где была эта статья, когда мы писали сложные синхронные приложения?..
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Фильтры исключений в CLR