Рабочим названием платформы .NET было |
Анализ кода на CIL
Блоки обработки исключений в графе потока управления
Как известно, блоки обработки исключений в CIL реализованы в виде массива описателей, который хранится отдельно от CIL-кода. Для адекватного представления блоков обработки исключений нам придется добавить в граф потока управления специальные узлы, обозначающие входы в блоки, а также специальные дуги, отражающие взаимосвязи между ними. Кроме того, мы обобщим понятие блока, введя так называемый блок тела метода.
Блоки, представленные в графе потока управления, можно разделить на четыре основные категории:
- Блок тела метода - главный блок графа, в который непосредственно или транзитивно входят все остальные узлы графа. Этот блок содержится в графе в единственном экземпляре и задает точку входа в граф (в примере он был помечен строкой "Метод print").
- Защищенный блок - соответствует try-блоку в программе. При выходе из защищенного блока управление может передаваться на один или несколько блоков обработки исключений.
- Блок обработки исключений - прикреплен к защищенному блоку и может получить управление при выходе из этого защищенного блока. В графе существуют три типа блоков обработки исключений: блок с фильтрацией по типу (catch-блок), блок с пользовательской фильтрацией и finally/fault-блок.
- Блок фильтрации - прикреплен к блоку обработки исключений с пользовательской фильтрацией и осуществляет принятие решения о передачи управления на обработчик.
Независимо от категории, к которой принадлежит блок, он имеет ровно один вход - входной узел, а выход из него может осуществляться только через один или несколько выходных узлов.
Схема обработки исключений отражена в структуре графа с помощью введения дополнительных связей между защищенным блоком и блоками обработки исключений. Так, каждый защищенный блок имеет ссылки на соответствующие блоки обработки исключений. При этом ссылки пронумерованы в том порядке, в каком происходит выполнение обработчиков исключений. Другими словами, обработка исключений требует введения в граф особых дуг, которые отражают не передачу управления между инструкциями, а последовательность обработчиков исключений, присоединенных к защищенному блоку (см. рис. 4.2).
Блок обработки исключений с пользовательской фильтрацией имеет более сложную структуру, чем другие блоки обработки исключений. Он соединен дополнительной дугой с блоком фильтрации. Подразумевается, что при активации блока с пользовательской фильтрацией управление сначала передается на этот блок фильтрации, который принимает решение о том, следует или нет передавать управление собственно на обработчик.
Проиллюстрируем следующим примером особенности графа потока управления с блоками обработки исключений:
.method private static int32 checkedAdd(int32 x, int32 y) { .locals init (int32 result) .try { ldarg.0 ldarg.1 add.ovf stloc.0 leave.s exit } catch System.OverflowException { pop ldc.i4.0 stloc.0 leave.s exit } exit: ldloc.0 ret }
Граф потока управления для метода checkedAdd показан на рис. 4.3.