CA2115: вызывайте GC.KeepAlive при использовании собственных ресурсов
TypeName |
CallGCKeepAliveWhenUsingNativeResources |
CheckId |
CA2115 |
Категория |
Microsoft.Security |
Критическое изменение |
Не критическое |
Причина
Метод, объявленный в типе, содержащем метод завершения, ссылается на поле IntPtr или UIntPtr, однако не вызывает метод GC.KeepAlive.
Описание правила
Сборка мусора завершает объект в том случае, если на него больше нет ссылок в управляемом коде.Ссылки на объект из машинного кода не препятствуют сборке мусора.Данное правило обнаруживает ошибки, которые могут возникать из-за завершения неуправляемых ресурсов, по-прежнему используемых в машинном коде.
Данное правило предполагает, что в полях IntPtr и UIntPtr хранятся указатели на неуправляемые ресурсы.Поскольку назначением метода завершения является освобождение неуправляемых ресурсов, правило предполагает, что метод завершения освободит неуправляемые ресурсы, на которые ссылаются указатели, содержащиеся в полях.Это правило также предполагает, что метод ссылается на поле указателя для передачи неуправляемого ресурса в машинный код.
Устранение нарушений
Чтобы устранить нарушение данного правила, добавьте вызов KeepAlive в метод, передающий в качестве аргумента текущий экземпляр (this в C# и C++).Поместите этот вызов после последней строки кода, в котором объект должен быть защищен от сборки мусора.Непосредственно после вызова KeepAlive объект снова считается готовым для сборки мусора при условии, что на него нет ссылок из управляемого кода.
Отключение предупреждений
В данном правиле используется несколько предположений, которые могут привести к ложным положительным результатам.Отключение предупреждений для этого правила безопасно, если выполняются следующие условия.
Прежде чем отключать другие сообщения, тщательно изучите их.Правило обнаруживает ошибки, воспроизведение и отладка которых крайне затруднительна.
Пример
В следующем примере BadMethod не включает вызов GC.KeepAlive и поэтому не нарушает правило.Метод GoodMethod содержит исправленный код.
Примечание |
---|
Данный пример выполнен в псевдокоде. Хотя код будет компилироваться и выполняться, предупреждение не будет показано, так как не создается и не освобождается неуправляемый ресурс. |
using System;
namespace SecurityRulesLibrary
{
class IntPtrFieldsAndFinalizeRequireGCKeepAlive
{
private IntPtr unmanagedResource;
IntPtrFieldsAndFinalizeRequireGCKeepAlive()
{
GetUnmanagedResource (unmanagedResource);
}
// The finalizer frees the unmanaged resource.
~IntPtrFieldsAndFinalizeRequireGCKeepAlive()
{
FreeUnmanagedResource (unmanagedResource);
}
// Violates rule:CallGCKeepAliveWhenUsingNativeResources.
void BadMethod()
{
// Call some unmanaged code.
CallUnmanagedCode(unmanagedResource);
}
// Satisfies the rule.
void GoodMethod()
{
// Call some unmanaged code.
CallUnmanagedCode(unmanagedResource);
GC.KeepAlive(this);
}
// Methods that would typically make calls to unmanaged code.
void GetUnmanagedResource(IntPtr p)
{
// Allocate the resource ...
}
void FreeUnmanagedResource(IntPtr p)
{
// Free the resource and set the pointer to null ...
}
void CallUnmanagedCode(IntPtr p)
{
// Use the resource in unmanaged code ...
}
}
}
См. также
Ссылки
Другие ресурсы
Implementing Finalize and Dispose to Clean Up Unmanaged Resources