Udostępnij za pośrednictwem


CA2115: Wywołaj GC.KeepAlive gdy używasz zasobów natywnych

Pozycja Wartość
Ruleid CA2115
Kategoria Microsoft.Security
Zmiana powodująca niezgodność Niezgodność

Przyczyna

Metoda zadeklarowana w typie z finalizatorem odwołuje się do System.IntPtr pola lub System.UIntPtr , ale nie wywołuje metody System.GC.KeepAlive.

Uwaga

Ta reguła została przestarzała. Aby uzyskać więcej informacji, zobacz Przestarzałe reguły.

Opis reguły

Odzyskiwanie pamięci finalizuje obiekt, jeśli nie ma więcej odwołań do niego w kodzie zarządzanym. Niezarządzane odwołania do obiektów nie uniemożliwiają odzyskiwania pamięci. Ta reguła wykrywa błędy, które mogą wystąpić, ponieważ kończy się działanie niezarządzanego zasobu, a wciąż jest on używany w kodzie niezarządzanym.

Ta reguła zakłada, że IntPtr i UIntPtr pola przechowują wskaźniki do niezarządzanych zasobów. Ponieważ celem finalizatora jest zwolnienie niezarządzanych zasobów, reguła zakłada, że finalizator zwolni niezarządzany zasób wskazywany przez pola wskaźnika. Ta reguła zakłada również, że metoda odwołuje się do pola wskaźnika, aby przekazać niezarządzany zasób do niezarządzanych kodów.

Jak naprawić naruszenia

Aby naprawić naruszenie tej reguły, dodaj wywołanie metody KeepAlive , przekazując bieżące wystąpienie (this w języku C# i C++) jako argument. Umieść wywołanie po ostatnim wierszu kodu, w którym obiekt musi być chroniony przed odzyskiwaniem pamięci. Natychmiast po wywołaniu KeepAlivemetody obiekt jest ponownie uznawany za gotowy do odzyskiwania pamięci przy założeniu, że nie ma do niego żadnych zarządzanych odwołań.

Kiedy pomijać ostrzeżenia

Ta reguła sprawia, że niektóre założenia mogą prowadzić do wyników fałszywie dodatnich. Możesz bezpiecznie pominąć ostrzeżenie z tej reguły, jeśli:

  • Finalizator nie zwalnia zawartości IntPtr pola lub UIntPtr , do których odwołuje się metoda .

  • Metoda nie przekazuje IntPtr pola lub UIntPtr do niezarządzanych kodów.

Uważnie przejrzyj inne wiadomości przed ich wykluczeniem. Ta reguła wykrywa błędy, które są trudne do odtworzenia i debugowania.

Przykład

W poniższym przykładzie BadMethod nie zawiera wywołania GC.KeepAlive metody i dlatego narusza regułę. GoodMethod zawiera poprawiony kod.

Uwaga

W tym przykładzie przedstawiono przykładowy kod. Mimo że kod jest kompilowany i uruchamiany, ostrzeżenie nie jest wyzwalane, ponieważ niezarządzany zasób nie jest tworzony ani zwalniany.

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 ...
      }
      
   }

}

Zobacz też