CA2115: Volejte GC.KeepAlive při použití nativních zdrojů

Zboží Hodnota
RuleId CA2115
Kategorie Microsoft.Security
Změna způsobující chybu Nenarušující

Příčina

Metoda deklarovaná v typu s finalizátorem odkazuje na System.IntPtr nebo System.UIntPtr pole, ale nevolá System.GC.KeepAlive.

Poznámka:

Toto pravidlo je zastaralé. Další informace najdete v tématu Zastaralá pravidla.

Popis pravidla

Uvolňování paměti dokončí objekt, pokud na něj ve spravovaném kódu nejsou žádné další odkazy. Nespravované odkazy na objekty nezabrání uvolňování paměti. Toto pravidlo zjistí chyby, které mohou nastat, protože nespravovaný prostředek je finalizován v době, kdy je stále používán nespravovaným kódem.

Toto pravidlo předpokládá, že IntPtr pole UIntPtr ukládají ukazatele na nespravované prostředky. Vzhledem k tomu, že účelem finalizátoru je uvolnit nespravované prostředky, pravidlo předpokládá, že finalizátor uvolní nespravovaný prostředek odkazovaný na pole ukazatele. Toto pravidlo také předpokládá, že metoda odkazuje na pole ukazatele, aby předal nespravovaný prostředek nespravovanému kódu.

Jak opravit porušení

Chcete-li opravit porušení tohoto pravidla, přidejte volání KeepAlive metody a předejte aktuální instanci (this v jazyce C# a C++) jako argument. Umístěte volání za poslední řádek kódu, kde musí být objekt chráněn před uvolňováním paměti. Ihned po volání KeepAlivese objekt znovu považuje za připravený pro uvolňování paměti za předpokladu, že neexistují žádné spravované odkazy na něj.

Kdy potlačit upozornění

Toto pravidlo vytváří určité předpoklady, které můžou vést k falešně pozitivním výsledkům. Upozornění z tohoto pravidla můžete bezpečně potlačit, pokud:

  • Finalizátor nezvolí obsah IntPtr pole nebo UIntPtr pole odkazovaného metodou.

  • Metoda nepředává kód nebo UIntPtr pole nespravovanému IntPtr kódu.

Před jejich vyloučením pečlivě zkontrolujte další zprávy. Toto pravidlo detekuje chyby, které se obtížně reprodukují a ladí.

Příklad

V následujícím příkladu BadMethod nezahrnuje volání GC.KeepAlive , a proto porušuje pravidlo. GoodMethod obsahuje opravený kód.

Poznámka:

Tento příklad je pseudokód. I když se kód zkompiluje a spustí, upozornění se neaktivuje, protože nespravovaný prostředek není vytvořen nebo uvolněn.

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

}

Viz také