Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 11 стр.

UptoLike

1.1.3.4. Верификация кода
При разработке платформы .NET было уделено много внимания
обеспечению безопасности выполняемого программного кода. С точки
зрения обеспечения безопасности можно привести следующую классифи-
кацию CIL-кода:
Недопустимый код (illegal code).
Это код, который не может быть обработан JIT-компилятором,
то есть не может быть транслирован в машинный код.
Допустимый код (legal code).
Это код, который может быть представлен в виде машинного
кода. При этом он может содержать вредоносные фрагменты
(например, вирусы) или ошибки, способные нарушить работу
не только программы, но и среды выполнения и даже операци-
онной системы.
Безопасный код (safe code).
Безопасный код не содержит вредоносных фрагментов (в том
числе ошибок) и не может повредить ни системе выполнения,
ни операционной системе, ни другим выполняемым програм-
мам.
Верифицируемый код (verifiable code).
Верифицируемый код – это код, безопасность которого может
быть строго доказана алгоритмом верификации, встроенным в
CLR.
Весь код, который поступает в JIT-компилятор, автоматически под-
вергается верификации. Верификатор платформы .NET реализует доста-
точно простой линейный алгоритм проверки правильной работы про-
граммного кода с типами данных и для каждого метода, входящего в сбор-
ку .NET, способен дать ответ на вопрос, проходит код этого метода вери-
фикацию или нет. В зависимости от настроек безопасности .NET система
выполнения может разрешить или не разрешить выполнять на машине
код, отбракованный верификатором.
Следует понимать, что верифицируемый код всегда является безо-
пасным, а обратное в общем случае неверно. То есть, можно себе предста-
вить такой CIL-код, который определенно является безопасным, но в си-
лу тех или иных причин не может пройти верификацию.
1.2. Общая система типов
Абстрагировавшись от конкретных особенностей .NET, можно ска-
зать, что основная цель системы типов заключается в предотвращении оп-
ределенного класса ошибок в программе до ее выпонения.
Введение в архитектуру Microsoft .NET Framework
9
жено на программиста, львиная доля времени, затрачиваемого на отладку
программы, приходится на борьбу с подобными ошибками.
Давайте перечислим типичные ошибки при управлении памятью
(некоторые из них особенно усугубляются в том случае, если в программе
существуют несколько указателей на один и тот же блок памяти):
1. Преждевременное освобождение памяти (premature free).
Эта беда случается, если мы пытаемся использовать объект, па-
мять для которого была уже освобождена. Указатели на такие
объекты называются висящими (dangling pointers), а обращение
по этим указателям дает непредсказуемый результат.
2. Двойное освобождение (double free).
Иногда бывает важно не перестараться и не освободить ненуж-
ный объект дважды.
3. Утечки памяти (memory leaks).
Когда мы постоянно выделяем новые блоки памяти, но забыва-
ем освобождать блоки, ставшие ненужными, память в конце
концов заканчивается.
4. Фрагментация адресного пространства (external fragmentation).
При интенсивном выделении и освобождении памяти может
возникнуть ситуация, когда непрерывный блок памяти опреде-
ленного размера не может быть выделен, хотя суммарный объем
свободной памяти вполне достаточен. Это происходит, если ис-
пользуемые блоки памяти чередуются со свободными блоками и
размер любого из свободных блоков меньше, чем нам нужно.
Проблема особенно критична в серверных приложениях, рабо-
тающих в течение длительного времени.
В программах, работающих в среде .NET, все вышеперечисленные
ошибки никогда не возникают, потому что эти программы используют ре-
ализованное в CLR автоматическое управление памятью, а именно –
сборщик мусора. Если не вдаваться в излишние на данном этапе изучения
.NET подробности, можно сказать, что работа сборщика мусора заключа-
ется в освобождении памяти, занятой ненужными объектами. При этом
сборщик мусора также умеет «двигать» объекты в памяти, тем самым уст-
раняя фрагментацию адресного пространства.
Все эти чудеса, которые творит сборщик мусора, возможны исклю-
чительно благодаря тому, что во время выполнения программы известны
типы всех используемых в ней объектов. Другими словами, данные, с ко-
торыми работает программа, находятся под полным контролем среды вы-
полнения и называются, соответственно, управляемыми данными (managed
data).
8
CIL и системное программирование в Microsoft .NET
8                           CIL и системное программирование в Microsoft .NET   Введение в архитектуру Microsoft .NET Framework                       9


жено на программиста, львиная доля времени, затрачиваемого на отладку           1.1.3.4. Верификация кода
программы, приходится на борьбу с подобными ошибками.                                При разработке платформы .NET было уделено много внимания
     Давайте перечислим типичные ошибки при управлении памятью                  обеспечению безопасности выполняемого программного кода. С точки
(некоторые из них особенно усугубляются в том случае, если в программе          зрения обеспечения безопасности можно привести следующую классифи-
существуют несколько указателей на один и тот же блок памяти):                  кацию CIL-кода:
        1. Преждевременное освобождение памяти (premature free).                         • Недопустимый код (illegal code).
           Эта беда случается, если мы пытаемся использовать объект, па-                   Это код, который не может быть обработан JIT-компилятором,
           мять для которого была уже освобождена. Указатели на такие                      то есть не может быть транслирован в машинный код.
           объекты называются висящими (dangling pointers), а обращение                  • Допустимый код (legal code).
           по этим указателям дает непредсказуемый результат.                              Это код, который может быть представлен в виде машинного
        2. Двойное освобождение (double free).                                             кода. При этом он может содержать вредоносные фрагменты
           Иногда бывает важно не перестараться и не освободить ненуж-                     (например, вирусы) или ошибки, способные нарушить работу
           ный объект дважды.                                                              не только программы, но и среды выполнения и даже операци-
        3. Утечки памяти (memory leaks).                                                   онной системы.
           Когда мы постоянно выделяем новые блоки памяти, но забыва-                    • Безопасный код (safe code).
           ем освобождать блоки, ставшие ненужными, память в конце                         Безопасный код не содержит вредоносных фрагментов (в том
           концов заканчивается.                                                           числе ошибок) и не может повредить ни системе выполнения,
        4. Фрагментация адресного пространства (external fragmentation).                   ни операционной системе, ни другим выполняемым програм-
           При интенсивном выделении и освобождении памяти может                           мам.
           возникнуть ситуация, когда непрерывный блок памяти опреде-                    • Верифицируемый код (verifiable code).
           ленного размера не может быть выделен, хотя суммарный объем                     Верифицируемый код – это код, безопасность которого может
           свободной памяти вполне достаточен. Это происходит, если ис-                    быть строго доказана алгоритмом верификации, встроенным в
           пользуемые блоки памяти чередуются со свободными блоками и                      CLR.
           размер любого из свободных блоков меньше, чем нам нужно.                  Весь код, который поступает в JIT-компилятор, автоматически под-
           Проблема особенно критична в серверных приложениях, рабо-            вергается верификации. Верификатор платформы .NET реализует доста-
           тающих в течение длительного времени.                                точно простой линейный алгоритм проверки правильной работы про-
     В программах, работающих в среде .NET, все вышеперечисленные               граммного кода с типами данных и для каждого метода, входящего в сбор-
ошибки никогда не возникают, потому что эти программы используют ре-            ку .NET, способен дать ответ на вопрос, проходит код этого метода вери-
ализованное в CLR автоматическое управление памятью, а именно –                 фикацию или нет. В зависимости от настроек безопасности .NET система
сборщик мусора. Если не вдаваться в излишние на данном этапе изучения           выполнения может разрешить или не разрешить выполнять на машине
.NET подробности, можно сказать, что работа сборщика мусора заключа-            код, отбракованный верификатором.
ется в освобождении памяти, занятой ненужными объектами. При этом                    Следует понимать, что верифицируемый код всегда является безо-
сборщик мусора также умеет «двигать» объекты в памяти, тем самым уст-           пасным, а обратное в общем случае неверно. То есть, можно себе предста-
раняя фрагментацию адресного пространства.                                      вить такой CIL-код, который определенно является безопасным, но в си-
     Все эти чудеса, которые творит сборщик мусора, возможны исклю-             лу тех или иных причин не может пройти верификацию.
чительно благодаря тому, что во время выполнения программы известны
типы всех используемых в ней объектов. Другими словами, данные, с ко-
торыми работает программа, находятся под полным контролем среды вы-             1.2. Общая система типов
полнения и называются, соответственно, управляемыми данными (managed
data).                                                                                Абстрагировавшись от конкретных особенностей .NET, можно ска-
                                                                                зать, что основная цель системы типов заключается в предотвращении оп-
                                                                                ределенного класса ошибок в программе до ее выпонения.