Используйте SafeHandle для инкапсуляции машинных ресурсов
Обновлен: Ноябрь 2007
TypeName |
UseSafeHandleToEncapsulateNativeResources |
CheckId |
CA2006 |
Категория |
Microsoft.Reliability |
Критическое изменение |
Не критическое |
Причина
Управляемый код использует указатель IntPtr для доступа к неуправляемым ресурсам.
Описание правила
Использование указателя IntPtr в управляемом коде может привести к возникновению проблем безопасности и надежности. Необходимо изучить все случаи использования указателя IntPtr, чтобы определить, не следует ли использовать вместо него класс SafeHandle или другую подобную технологию. Проблемы возникают, когда указатель IntPtr представляет некоторый неуправляемый ресурс, например память, дескриптор файла, сокет и п. п., владельцем которого считается управляемый код. То есть ожидается, что управляемый код освободит данный ресурс, и, если этого не происходит, возникает утечка ресурсов.
Кроме того, если к указателю IntPtr разрешен одновременный доступ из нескольких потоков и способ освобождения ресурса представлен указателем IntPtr, также возникают проблемы надежности или безопасности. Эти проблемы связаны с повторным использованием значения IntPtr после освобождения ресурса при одновременном использовании ресурса из другого потока. Это приводит к состоянию гонки, когда один поток может считывать и записывать данные, связанные с неверным ресурсом. Например, если в типе хранится дескриптор ОС в виде указателя IntPtr и пользователям разрешено одновременно вызывать метод Close и любой другой метод с помощью этого дескриптора без выполнения какой-либо синхронизации, то в коде возникает проблема повторного использования дескриптора.
Проблема повторного использования дескриптора приводит к повреждению данных, а иногда и к уязвимостям системы безопасности. Класс SafeHandle и его одноуровневый класс CriticalHandle предоставляют механизм инкапсуляции неуправляемого дескриптора в ресурсе, что позволяет избежать подобных проблем многопоточного выполнения. Кроме того, класс SafeHandle и его одноуровневый класс CriticalHandle можно использовать для решения других проблем многопоточности, например для строгого контроля времени существования управляемых объектов, содержащих копию неуправляемого дескриптора, между вызовами неуправляемых методов. В таких случаях зачастую можно удалить вызовы метода GC.KeepAlive. При использовании класса SafeHandle и, в меньшей степени, класса CriticalHandle возрастают накладные расходы, которые чаще всего удается снизить за счет аккуратного проектирования.
Предотвращение нарушений
Для безопасного управления неуправляемыми ресурсами следует вместо указателя IntPtr использовать класс SafeHandle.
Отключение предупреждений
Не следует отключать данные предупреждения.