다음을 통해 공유


CA2115: 네이티브 리소스를 사용하는 경우에는 GC.KeepAlive를 호출하십시오.

TypeName

CallGCKeepAliveWhenUsingNativeResources

CheckId

CA2115

범주

Microsoft.Security

변경 수준

주요 변경 아님

원인

종료자가 있는 형식에 선언된 메서드가 System.IntPtr 또는 System.UIntPtr 필드를 참조하지만 GC.KeepAlive를 호출하지 않습니다.

규칙 설명

관리 코드에서 더 이상 개체를 참조하지 않으면 가비지 수집에서 해당 개체를 종료합니다. 개체에 대한 관리되지 않는 참조가 있어도 가비지 수집이 수행됩니다. 이 규칙에서는 관리되지 않는 리소스가 비관리 코드에서 여전히 사용되고 있는데 종료되려고 할 경우 발생할 수 있는 오류를 감지합니다.

이 규칙에서는 IntPtrUIntPtr 필드에 관리되지 않는 리소스에 대한 포인터가 저장된다고 가정합니다. 종료자의 목적은 관리되지 않는 리소스를 해제하는 것이므로 이 규칙에서는 포인터 필드에서 가리키는 관리되지 않는 리소스를 종료자가 해제한다고 가정합니다. 또한 관리되지 않는 리소스를 비관리 코드로 전달하는 포인터 필드를 메서드가 참조하고 있다고 가정합니다.

위반 문제를 해결하는 방법

이 규칙 위반 문제를 해결하려면 KeepAlive 호출을 메서드에 추가하고 현재 인스턴스(C# 및 C++에서는 this)를 인수로 전달합니다. 가비지 수집으로부터 개체를 보호해야 하는 코드의 마지막 줄 이후에 호출을 배치합니다. KeepAlive 호출 이후부터는 개체에 대한 관리되는 참조가 없다고 간주되어 개체가 다시 가비지 수집이 가능한 상태가 됩니다.

경고를 표시하지 않는 경우

이 규칙에서 미리 가정하는 사항으로 인해 가양성(false positives)이 나타날 수 있습니다. 다음과 같은 경우 이 규칙에서 경고를 표시하지 않아도 안전합니다.

  • 종료자가 메서드에서 참조하는 IntPtr 또는 UIntPtr 필드의 내용을 해제하지 않는 경우

  • 메서드가 IntPtr 또는 UIntPtr 필드를 비관리 코드로 전달하지 않는 경우

이들을 제외하기 전에 다른 메시지를 충분히 검토하십시오. 이 규칙에서 감지하는 오류는 재현하거나 디버깅하기 어렵습니다.

예제

이 예제에서 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 ...
      }

   }

}

참고 항목

참조

Finalize 및 Dispose를 구현하여 관리되지 않는 리소스 정리

GC.KeepAlive

System.IntPtr

Object.Finalize

System.UIntPtr