Partager via


CA2115 : Appelez GC.KeepAlive lorsque vous utilisez des ressources natives

Élément Valeur
ID de la règle CA2115
Category Microsoft.Security
Modification avec rupture Sans rupture

Cause

Une méthode déclarée dans un type avec un finaliseur référence un champ System.IntPtr ou System.UIntPtr, mais n’appelle pas System.GC.KeepAlive.

Notes

Cette règle est déconseillée. Pour plus d’informations, consultez Règles dépréciées.

Description de la règle

Garbage collection finalise un objet s’il n’y a plus de références à cet objet dans le code managé. Les références non managées aux objets n’empêchent pas le garbage collection. Cette règle détecte les erreurs susceptibles de se produire du fait qu’une ressource non managée est en cours de finalisation alors qu’elle est encore utilisée dans un code non managé.

Cette règle suppose que les champs IntPtr et UIntPtr stockent des pointeurs vers des ressources non managées. L'objectif d'un finaliseur étant de libérer les ressources non managées, la règle suppose que le finaliseur libérera la ressource non managée désignée par les champs de pointeurs. Cette règle suppose également que la méthode référence le champ de pointeur pour transmettre la ressource non managée au code non managé.

Comment corriger les violations

Pour corriger une violation de cette règle, ajoutez un appel à KeepAlive à la méthode, en passant l’instance actuelle (this en C# et C++) en tant qu’argument. Positionnez l'appel après la dernière ligne de code où l'objet doit être protégé contre le garbage collection. Aussitôt après l’appel à KeepAlive, l’objet est à nouveau considéré comme prêt pour le garbage collection en supposant qu’il n’est associé à aucune référence managée.

Quand supprimer les avertissements

Cette règle repose sur certaines hypothèses qui peuvent entraîner des faux positifs. Vous pouvez ignorer en toute sécurité un avertissement de cette règle si :

  • Le finaliseur ne libère pas le contenu du champ IntPtr ou UIntPtr référencé par la méthode.

  • La méthode ne transmet pas le champ IntPtr ou UIntPtr au code non managé.

Examinez attentivement les autres messages avant de les ignorer. Cette règle détecte les erreurs difficiles à reproduire et à déboguer.

Exemple

Dans l’exemple suivant, BadMethod n’inclut pas d’appel à GC.KeepAlive et enfreint donc la règle. GoodMethod contient le code corrigé.

Notes

Cet exemple est pseudo-code. Bien que le code se compile et s'exécute, l'avertissement n'est pas déclenché parce qu'une ressource non managée n'est pas créée ou libérée.

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

}

Voir aussi