CA2115: 네이티브 리소스를 사용하는 경우에는 GC.KeepAlive를 호출하십시오.
TypeName |
CallGCKeepAliveWhenUsingNativeResources |
CheckId |
CA2115 |
범주 |
Microsoft.Security |
변경 수준 |
주요 변경 아님 |
원인
종료자가 있는 형식에 선언된 메서드가 System.IntPtr 또는 System.UIntPtr 필드를 참조하지만 GC.KeepAlive를 호출하지 않습니다.
규칙 설명
관리 코드에서 더 이상 개체를 참조하지 않으면 가비지 수집에서 해당 개체를 종료합니다. 개체에 대한 관리되지 않는 참조가 있어도 가비지 수집이 수행됩니다. 이 규칙에서는 관리되지 않는 리소스가 비관리 코드에서 여전히 사용되고 있는데 종료되려고 할 경우 발생할 수 있는 오류를 감지합니다.
이 규칙에서는 IntPtr 및 UIntPtr 필드에 관리되지 않는 리소스에 대한 포인터가 저장된다고 가정합니다. 종료자의 목적은 관리되지 않는 리소스를 해제하는 것이므로 이 규칙에서는 포인터 필드에서 가리키는 관리되지 않는 리소스를 종료자가 해제한다고 가정합니다. 또한 관리되지 않는 리소스를 비관리 코드로 전달하는 포인터 필드를 메서드가 참조하고 있다고 가정합니다.
위반 문제를 해결하는 방법
이 규칙 위반 문제를 해결하려면 KeepAlive 호출을 메서드에 추가하고 현재 인스턴스(C# 및 C++에서는 this)를 인수로 전달합니다. 가비지 수집으로부터 개체를 보호해야 하는 코드의 마지막 줄 이후에 호출을 배치합니다. KeepAlive 호출 이후부터는 개체에 대한 관리되는 참조가 없다고 간주되어 개체가 다시 가비지 수집이 가능한 상태가 됩니다.
경고를 표시하지 않는 경우
이 규칙에서 미리 가정하는 사항으로 인해 가양성(false positives)이 나타날 수 있습니다. 다음과 같은 경우 이 규칙에서 경고를 표시하지 않아도 안전합니다.
이들을 제외하기 전에 다른 메시지를 충분히 검토하십시오. 이 규칙에서 감지하는 오류는 재현하거나 디버깅하기 어렵습니다.
예제
이 예제에서 BadMethod는 규칙을 위반합니다. 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 ...
}
}
}