Я работаю над проектом, используя библиотеку парсеров ANTLR для С#. Я построил грамматику, чтобы разобрать текст, и он работает хорошо. Однако, когда парсер сталкивается с незаконным или неожиданным токеном, он выдает одно из многих исключений. Проблема в том, что в некоторых случаях (не все) мой блок try/catch не поймает его и вместо этого прекратит выполнение как необработанное исключение.
Проблема для меня в том, что я не могу воспроизвести эту проблему нигде, кроме моего полного кода. Стек вызовов показывает, что исключение определенно встречается в моем блоке try/catch (Exception). Единственное, что я могу придумать, это то, что между моим кодом и кодом, генерирующим исключение, есть несколько вызовов сборки ANTLR, и в этой библиотеке нет отладки, поэтому я не могу пройти через нее. Интересно, запрещают ли отказоустойчивые сборки блокировать исключение? Стек вызова выглядит следующим образом; внешние вызовы сборки находятся в Antlr.Runtime:
Expl.Itinerary.dll!TimeDefLexer.mTokens() Line 1213 C# Antlr3.Runtime.dll!Antlr.Runtime.Lexer.NextToken() + 0xfc bytes Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.FillBuffer() + 0x22c bytes Antlr3.Runtime.dll!Antlr.Runtime.CommonTokenStream.LT(int k = 1) + 0x68 bytes Expl.Itinerary.dll!TimeDefParser.prog() Line 109 + 0x17 bytes C# Expl.Itinerary.dll!Expl.Itinerary.TDLParser.Parse(string Text = "", Expl.Itinerary.IItinerary Itinerary = {Expl.Itinerary.MemoryItinerary}) Line 17 + 0xa bytes C#
Фрагмент кода с самого нижнего вызова в Parse() выглядит так:
try {
// Execution stopped at parser.prog()
TimeDefParser.prog_return prog_ret = parser.prog();
return prog_ret == null ? null : prog_ret.value;
}
catch (Exception ex) {
throw new ParserException(ex.Message, ex);
}
Для меня предложение catch (Exception) должно было занять какое-либо исключение. Есть ли причина, почему это не так?
Обновление: Я проследил через внешнюю сборку с Reflector и не обнаружил никаких доказательств пронизывания. Похоже, что сборка представляет собой обычный служебный класс для ANTLR сгенерированного кода. Исключением является метод TimeDefLexer.mTokens(), а его тип - NoViableAltException, который происходит из RecognitionException → Exception. Это исключение выдается, когда лексер не может понять следующий токен в потоке; другими словами, недопустимый ввод. Это исключение SUPPOSED должно произойти, однако оно должно быть захвачено моим блоком try/catch.
Кроме того, реорганизация ParserException действительно не имеет отношения к этой ситуации. Это слой абстракции, который принимает какое-либо исключение во время разбора и конвертируется в мое собственное исключение ParserException. Проблема обработки исключений, с которой я столкнулась, никогда не достигает этой строки кода. Фактически, я прокомментировал часть "throw new ParserException" и получил тот же результат.
Еще одна вещь, я изменил исходный блок try/catch, о котором идет речь, вместо этого поймать NoViableAltException, устраняя любую путаницу наследования. Я все равно получил тот же результат.
Кто-то однажды предположил, что иногда VS является overactive при перехвате обработанных исключений в режиме отладки, но эта проблема также возникает в режиме выпуска.
Человек, я все еще в тупике! Раньше я не упоминал об этом, но я запускаю VS 2008, и весь мой код - 3.5. Внешняя сборка - 2.0. Кроме того, некоторые из моих подклассов кода класса в сборке 2.0. Может ли возникнуть ошибка в версии?
Обновление 2:. Я смог устранить конфликт версии .NET, портируя соответствующие части моего .NET 3.5-кода в проект .NET 2.0 и реплицируя тот же сценарий. Я смог реплицировать одно и то же необработанное исключение при постоянной работе в .NET 2.0.
Я узнал, что ANTLR недавно выпустила 3.1. Итак, я обновился с 3.0.1 и повторил попытку. Оказывается, сгенерированный код немного реорганизуется, но в моих тестовых случаях происходит одно и то же необработанное исключение.
Обновление 3: Я воспроизвел этот сценарий в упрощенном проекте VS 2008 . Не стесняйтесь загружать и проверять проект самостоятельно. Я применил все замечательные предложения, но пока не смог преодолеть это препятствие.
Если вы найдете обходной путь, пожалуйста, поделитесь своими результатами. Еще раз спасибо!
Спасибо, но VS 2008 автоматически разбивается на необработанные исключения. Кроме того, у меня нет диалога Debug- > Exceptions. Выпущенное NoViableAltException полностью предназначено и предназначено для обнаружения кода пользователя. Поскольку он не пойман как ожидалось, выполнение программы неожиданно приостанавливается как необработанное исключение.
Исключенное исключение выводится из Exception и нет многопоточности, идущей с ANTLR.