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

TypeName

CallGCKeepAliveWhenUsingNativeResources

CheckId

CA2115

Catégorie

Microsoft.Security

Modification avec rupture

Modification 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 GC.KeepAlive.

Description de la règle

L'opération garbage collection finalise un objet s'il ne figure plus de références à celui-ci dans un code managé. Des références non managées à des objets n'empêchent pas l'opération 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. Sachant que le but d'un finaliseur consiste à libérer des ressources non managées, la règle suppose que le finaliseur libère la ressource non managée vers laquelle pointent les champs de pointeurs. Cette règle suppose également que la méthode référence le champ de pointeur pour passer 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 en C++) en tant qu'argument. Positionnez l'appel après la dernière ligne de code où l'objet doit être protégé contre l'opération garbage collection. Immédiatement après l'appel à KeepAlive, l'objet est à nouveau considéré comme prêt pour l'opération garbage collection en partant du principe qu'il ne fasse l'objet d'aucune référence managée.

Quand supprimer les avertissements

Cette règle émet certaines hypothèses qui peuvent mener à des faux positifs. Vous pouvez supprimer sans risque un avertissement de cette règle si les conditions suivantes sont satisfaites :

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

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

Passez soigneusement en revue d'autres messages avant de les exclure. Cette règle détecte des erreurs difficiles de reproduire et à déboguer.

Exemple

Dans cet exemple, BadMethod viole la règle. GoodMethod contient le code corrigé.

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

Référence

Implémentation des méthodes Finalize et Dispose pour nettoyer des ressources non managées

GC.KeepAlive

System.IntPtr

Object.Finalize

System.UIntPtr