583
Освобождение.ресурсов.при.помощи.механизма.финализации
бождаемый другим потоком. Это называется атакой с повторным использованием
дескрипторов. Класс
SafeHandle
предотвращает это нарушение безопасности благо-
даря подсчету ссылок. В нем определено закрытое поле, исполняющее роль счетчика.
Когда производному от
SafeHandle
объекту присваивается корректный дескриптор,
счетчик приравнивается к 1. Всякий раз, когда производный от
SafeHandle
объект
передается как аргумент неуправляемому методу, CLR автоматически увеличивает
значение счетчика на единицу. Когда неуправляемый метод возвращает управление
управляемому коду, CLR уменьшает значение счетчика на ту же величину. Напри-
мер, вот как выглядит прототип Win32-функции
SetEvent
:
[DllImport("Kernel32", ExactSpelling=true)]
private static extern Boolean SetEvent(SafeWaitHandle swh);
При вызове этого метода и передаче ему ссылки на объект
SafeWaitHandle
CLR
увеличивает значение счетчика перед вызовом и уменьшает значение счетчика
сразу после вызова. Разумеется, операции со счетчиком выполняются способом,
безопасным по отношению к потокам. Как это повышает безопасность? Если другой
поток попытается освободить системный ресурс, оболочкой которого является объ-
ект
SafeHandle
, CLR узнает, что это ему не разрешено, потому что данный ресурс
используется неуправляемой функцией. Когда функция вернет управление про-
грамме, значение счетчика будет приравнено к 0 и ресурс освободится.
При написании или вызове кода, работающего с дескриптором (например,
IntPtr
), к нему можно обратиться из объекта
SafeHandle
, но подсчет ссылок при-
дется выполнять явно с помощью методов
DangerousAddRef
и
DangerousRelease
объекта
SafeHandle
. Обращение к исходному дескриптору происходит через метод
DangerousGetHandle
.
Нельзя не упомянуть о классе
CriticalHandle
, также определенном в про-
странстве имен
System.Runtime.InteropServices
. Он работает точно так же,
как и
SafeHandle
, но не поддерживает подсчет ссылок. В
CriticalHandle
и про-
изводных от него классах безопасность принесена в жертву повышению произво-
дительности (за счет отказа от счетчиков). Как и у
SafeHandle
, у
CriticalHandle
есть два производных типа —
CriticalHandleMinusOneIsInvalid
и
CriticalHand
leZeroOrMinusOneIsInvalid
. Так как Microsoft отдает предпочтение безопасности,
а не производительности системы, в библиотеке классов нет типов, производ-
ных от этих двух классов. Используйте типы, производные от
CriticalHandle
,
только когда высокая производительность необходима и оправдывает некоторое
ослабление защиты.
Do'stlaringiz bilan baham: