Подтвердить что ты не робот

Препятствует ли обработка исключений в С# стандарту ECMA-335?

Мое понимание основано на этой длинной, но фантастической статье, которая поддерживает поведение, указанное в спецификации С#.

Стандарт CLI (EMCA-335) показывает, что если подходящего улова нет, время выполнения должно немедленно прекратиться. Время выполнения .NET не делает этого, вместо этого оно, похоже, склоняется к поведению спецификации С# (EMCA-334).

Во-первых, мне кажется странным, что спецификация языка, как представляется, определяет поведение каркаса. Во-вторых, они, кажется, противоречат.

  • Они противоречат друг другу, или я получаю неправильный смысл документа?
  • Должно ли время выполнения работать с обработкой исключений, чтобы соответствовать стандарту?

Как необязательный вопрос, какой из них является "правильным", как в случае, если я должен написать свою собственную реализацию CLI, которую я должен использовать? Обратите внимание, что документ EMCA-335 (CLI) был обновлен два месяца назад, где EMCA-334 (С#) был обновлен еще в 2006 году.


ECMA-335 Раздел я Раздел 12.4.2.5

  • Когда возникает исключение, CLI ищет массив для первого защищенного блока, который
    • Защищает регион, включая текущий указатель инструкции, и
    • Является блоком обработчика catch и
    • Чей фильтр хочет обработать исключение
  • Если совпадение не найдено в текущем методе, выполняется поиск вызывающего метода и т.д. Если совпадение не найдено, CLI удалит трассировку стека и прервет работу программы.

  • Если совпадение найдено, CLI переводит стек обратно в только что находящуюся точку, но на этот раз вызывает обработчики finally и fault. Затем он запускает соответствующий обработчик исключений.

С# Спецификация §15.9.5 и §15.10 (§8.9.5 и §8.10 на MSDN)

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

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

  • В функции, которая вызывает исключение:
    • Ищет соответствующее предложение catch в каждом заявлении try
      • Выполняет оператор catch, если он существует
    • Блок finally выполняется, если он существует
  • Если не было обработчика, вышеуказанные шаги повторяются в вызывающей функции
  • Если обработка исключений завершает все вызовы членов функции в текущем потоке, указывая, что поток не имеет обработчика исключения, то сам поток завершается. Влияние такого завершения определяется реализацией.
4b9b3361

Ответ 1

Я думаю, что это может быть просто расплывчатой ​​формулировкой.

Если совпадение не найдено в текущем методе, выполняется поиск метода вызова и т.д. Если совпадение не найдено, CLI удалит трассировку стека и прервет работу программы.

Хорошо, это правда в С#. Мы все знаем, что если у нас нет catch, то исключение приведет к снижению нашей программы.

Если совпадение найдено, CLI переводит стек обратно в только что находящуюся точку, но на этот раз вызывает обработчики finally и fault. Затем он запускает соответствующий обработчик исключений.

И это соответствует тому, что мы знаем из С#. Если есть несколько блоков finally (мы не можем видеть fault), чтобы справиться с ними, когда мы поднимаемся вверх по стеку из исключения, которое бросается до нашего блока catch, они обрабатываются, но он останавливается там и не идет дальше в стек.

Много висит от того, как мы читаем "If", который запускает второй фрагмент, который я только что процитировал. Вы читаете его как "если... тогда... иначе ничего подобного". Его можно было прочитать, хотя в качестве первого отрывка, идентифицирующего точку в стеке, которая будет идти: Если был catch, тогда он подошел к этой точке. Если улов нет, тогда он доходит до самой вершины стека, и мы получаем свалку и прерываем. Обработчики finally (и обработчики ошибок) все еще вызываются, но дело не в соответствующем методе обработчика.

Ваше чтение является самым буквальным, а мое - тем, что немного тянет. Тем не менее, моя совместимость с описанием finally в другом месте того же стандарта, наиболее близко

Ответ 2

Здесь нет конфликта. Спецификация языка С# сформулирована следующим образом:

Если оператор try не имеет ограничений catch или если исключение catch не соответствует исключению:
 • Если оператор try имеет окончательный блок, выполняется блок finally.
 • Исключение распространяется на следующий прилагаемый оператор try.

Bullet 2 здесь специально не говорит, что происходит, когда нет следующего прилагаемого утверждения try. Для этого вернитесь к концу 8.9.5:

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

Это определенно определяется реализацией. Помимо спецификации Ecma 335, политика обработки исключений является настраиваемым элементом в Microsoft CLR. Контролируется ICLRPolicyManager:: SetActionOnFailure(). В свою очередь, настраивается на хосте по умолчанию с элементом файла <legacyUnhandledExceptionPolicy> app.exe.config. По умолчанию для CLR версии 2.0 и выше необходимо немедленно завершить работу программы.

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

Ответ 3

цитированная статья в O.P. имеет неправильное базовое предположение:

Конечно, мы не можем говорить об управляемых исключениях без предварительного рассмотрения Windows Обработка структурированных исключений (SEH). И нам также нужно посмотреть на исключение С++ модель. Это потому, что реализованы как управляемые исключения, так и исключения С++ над основным механизмом SEH, и поскольку управляемые исключения должны взаимодействовать с исключениями SEH и С++.

Стандарт CLR (ISO 23271/ECMA 335) преднамеренно связан с платформой. Реализация Microsoft - одна из многих возможных реализаций (Mono, конечно, другая).

Взаимодействие с обработкой исключений Structured Exception и обработкой исключений С++ - это, я уверен, выбор Microsoft, а не требование ISO 23271.