CA2006: используйте SafeHandle для инкапсуляции машинных ресурсов
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.Примеры см. в разделе справки, посвященном SafeHandle.
Отключение предупреждений
Не следует отключать данные предупреждения.