Cet article a fait l'objet d'une traduction automatique.

Les coulisses du CLR

Gestion des endommagé état exceptions

Andrew Pardoe

Cet article repose sur une version préliminaire de Visual Studio 2010. Toutes les informations sont sujets à modification.

Contenu

Que sont exactement les exceptions ?
Exceptions SEH Win32 et System.Exception
Code géré et sur SEH
Exceptions état endommagé
Il est toujours incorrect utiliser réception (exception e)
Code intelligemment

Avez-vous jamais écrit code qui n'est pas tout à fait exact mais est suffisamment proche ? Avez vous deviez écrire du code qui fonctionne correctement lorsque tout se passe bien, mais vous n'êtes pas tout à fait sûr que se passe-t-il lorsque quelque chose se passe ? Il y a une instruction simple, incorrecte qui est trouve probablement dans certains code que vous avez écrit ou ont maintenir : catch (exception e). Il semble Cependant et simple, mais cette instruction peu peut provoquer beaucoup de problèmes lorsqu'il échoue à faire ce que vous attendez.

Si vous avez déjà vu code qui utilise des exceptions ne la manière dont le code suivant, puis vous devez lire cette colonne :

public void FileSave(String name)
{
    try
    {
      FileStream fs = new FileStream(name, FileMode.Create);
    }
    catch (Exception)
    {
      throw new System.IO.IOException("File Open Error!");
    }
}

L'erreur dans ce code est commun : Il est plus simple d'écrire du code pour intercepter tous les exceptions Qu'est d'intercepter exactement les exceptions qui peuvent être générées par l'exécution de code dans le bloc try. Mais vous par l'interception de la base de la hiérarchie d'exception, vous retrouvez swallowing une exception de n'importe quel type et il conversion en une IOException.

Gestion des exceptions sont une des ces zones sur les plupart des gens ont une connaissance pratique plutôt que de comprendre intimate. Je vais commencer par un peu d'informations générales expliquant exception Gestion du CLR point de vue pour ceux qui seront peut-être plus familiers de programmation native ou un ancien manuel Université de gestion des exceptions. Si vous êtes un pro ancien à Gestion des exceptions gérées, hésitez pas à passez directement à la section dans différents types d'exceptions ou le sur code géré et de structuré (SEH) de gestion des exceptions. Assurez-vous de lire les sections quelques dernière, cependant.

Que sont exactement les exceptions ?

Une exception est le signal survient quand une condition est détectée et qui n'a pas attendu dans l'exécution normale d'un thread de programme. Plusieurs agents peuvent détecter les conditions incorrectes et générer des exceptions. Code de programme (ou qu'il utilise le code de bibliothèque) peut lever types dérivés de System.Exception, le moteur d'exécution CLR peut générer des exceptions et code non managé peut générer des exceptions ainsi. Exceptions générées sur un thread d'exécution suivent le thread par code natif et géré, entre domaines d'application et, si ne pas pris en charge par le programme, traitées comme exceptions non gérées par le système d'exploitation.

Une exception indique que quelque chose d'incorrect est survenue. Bien que chaque exception gérée présente un type (tel que System.ArgumentException ou System.ArithmeticException), le type est uniquement explicite dans le contexte dans lequel l'exception est générée. Un programme peut gérer une exception si elle comprend les conditions qui a provoqué l'exception se produise. Mais si le programme ne gère l'exception, cela peut indiquer un nombre quelconque de choses incorrects. Et une fois que l'exception a quitté le programme, il est uniquement une signification très générale : quelque chose d'incorrect est survenue.

Lorsque Windows détecte qu'un programme ne gère une exception, il essaie de protéger le programme est conservée (fichiers sur disque, les paramètres du Registre, etc.) de données par termine le processus. Même si l'exception indiqué à l'origine des état du programme bénins, inattendue (comme l'échec de pop d'une pile vide) il semble être un problème sérieux lorsque Windows détecte qu'il car le système d'exploitation n'a pas le contexte pour interpréter correctement l'exception. Un thread unique dans un AppDomain peut utiliser une instance CLR ensemble vers le bas en ne pas gérer une exception (voir figure 1 ).

fig01.gif

Figure 1 une non thread gérées exception provoque la procédure afin de terminaison de l'ensemble

Si exceptions sont donc dangereuses, pourquoi sont elles donc courantes ? Tout comme motorcycles et vues de chaîne, la puissance brute des exceptions les rend très utile. Flux de données normale sur un thread de programme passe de fonction via des appels et renvoie. Chaque appel à une fonction crée un cadre de l'exécution de la pile ; chaque retour détruit ce cadre. À part modification état global, le seul flux de données dans un programme est obtenue à passer les données entre les cadres contigus que les paramètres de fonction ou de valeurs de retour. En l'absence de la gestion des exceptions, chaque appelant souhaite vérifier la réussite de la fonction qui elle appelée (ou simplement suppose que tout est toujours OK).

La plupart des API Win32 renvoie une valeur non nulle pour indiquer l'échec car Windows n'est pas utiliser Gestion des exceptions. Le programmeur doit placer chaque appel de fonction avec le code qui vérifie la valeur renvoyée de la fonction appelée. Par exemple, ce code de la documentation MSDN sur la façon de classer les fichiers dans un répertoire vérifie explicitement chaque appel pour la réussite. L'appel de FindNextFile(...) est encapsulé dans une vérification pour vérifier si le retour est non nulle. Si l'appel échoue puis un distinct appels de fonction, () GetLastError, fournit des détails de la condition exceptionnelle. Notez que chaque appel doit être archivé pour la réussite sur le cadre suivant étant les valeurs renvoyées nécessairement limitées à l'étendue locale fonction :

// FindNextFile requires checking for success of each call 
while (FindNextFile(hFind, &ffd) != 0); 
dwError = GetLastError(); 
if (dwError != ERROR_NO_MORE_FILES) 
{ 
  ErrorHandler(TEXT("FindFirstFile")); 
} 
FindClose(hFind); 
return dwError; 

Une condition d'erreur ne pouvez transmettre à partir de la fonction contenant la condition inattendue à appelant cette fonction. Exceptions ont la puissance afin de transmettre les résultats de l'exécution d'une fonction hors de portée de la fonction en cours à chaque cadre jusqu'à la pile jusqu'à ce qu'il atteigne le cadre qui sait comment gérer la condition inattendue. Système d'exception du CLR (appelé un système d'exception deux passes) fournit l'exception à chaque prédécesseur sur la pile du thread appel, commençant par l'appelant et continuer jusqu'à ce qu'une fonction indique qu'il traite l'exception (cette procédure est appelée la première phase).

Le système d'exception est déroulage ensuite l'état de chaque cadre sur la pile d'appel entre où l'exception est générée et où elle sera gérée (connu en tant que la deuxième phase). Comme la pile unwinds, le CLR exécutera les clauses de panne et enfin les clauses dans chaque cadre car elle est déroulée. Ensuite, la clause catch dans le cadre du traitement est exécutée.

Étant donné que le CLR vérifie chaque prédécesseur dans la pile des appels il est inutile pour l'appelant pour un bloc catch, l'exception peut être interceptée n'importe où haut de la pile. Au lieu de devoir immédiatement vérifier le résultat de chaque appel de fonction de code, un programmeur peut gérer les erreurs dans un endroit loin d'où l'exception a été générée. L'utilisation de codes d'erreur nécessite au programmeur d'inspecter et de transmettre sur un code d'erreur à chaque trame de pile jusqu'à ce qu'il atteigne l'endroit où la condition erronée peut être traitée. Gestion des exceptions permet de libérer le programmeur d'inspecter l'exception à chaque image sur la pile.

Pour plus d'informations en générant des types d'exceptions personnalisé, consultez » Gestion des erreurs : générant des types d'exception personnalisés à partir d'une application serveur COM + géré".

Exceptions SEH Win32 et System.Exception

Il agit un effet côté intéressant provient de la capacité pour intercepter des exceptions loin d'où l'exception a été générée. Un thread de programme pouvez recevoir des exceptions de programmes de n'importe quel cadre actif dans la pile des appels sans savoir où l'exception a été générée. Mais exceptions n'est pas toujours représentent une condition d'erreur qu'il détecte : un thread de programme peut également provoquer une exception en dehors du programme.

Si l'exécution d'un thread entraîne un processeur de panne, puis contrôle est transféré vers le noyau du système d'exploitation, qui présente la panne au thread comme exception SEH. Comme votre catch bloc ne sais où sur pile le thread qu'une exception a été générée, il n'est pas besoin de savoir exactement à quel moment le noyau du système d'exploitation déclenché l'exception SEH.

Windows vous signale threads de programme sur les exceptions du système d'exploitation à l'aide de SEH. Le code géré programmeurs rarement verront ces parce que le CLR empêche généralement les types d'erreurs indiquées par les exceptions SEH. Mais si Windows génère une exception SEH, le CLR fournira il au code géré. Bien que les exceptions SEH dans du code géré soient rares, dangereux du code managé peut générer un STATUS_­ACCESS_VIOLATION qui indique que le programme a tenté d'accéder à la mémoire non valide.

Pour des détails sur SEH, voir la rubrique article de Matt Pietrek » Un cours intensif de la profondeur de Win32 traitement structuré des exceptions« en le 1997 janvier émettre de Microsoft Systems Journal .

Exceptions SEH sont une autre classe de ces exceptions générées par votre programme. Un programme peut déclencher une exception car elle avez essayé d'afficher un article à partir d'une pile vide ou que vous avez essayé d'ouvrir un fichier qui n'existe pas. Toutes ces exceptions sens dans le contexte d'exécution de votre programme. Exceptions SEH voir un contexte à l'extérieur de votre programme. Une violation d'accès (AV), par exemple, indique une écriture tentée dans la mémoire non valide. Contrairement aux erreurs de programme, une exception SEH indique que l'intégrité du processus de l'exécution peut avoir été compromise. Mais même si exceptions SEH diffère des exceptions qui dérivent de System.Exception, lorsque le CLR fournit les exceptions SEH à un thread géré il peut être interceptée avec une instruction catch (exception e).

Certains systèmes tente de séparer ces deux types d'exceptions. Le compilateur Microsoft Visual C++ fait la distinction entre les exceptions générées par une instruction throw C++ et les exceptions SEH Win32 si vous compilez votre programme avec le commutateur /EH. Cette séparation est utile, car un programme normal ne sait pas comment traiter les erreurs qu'il n'a pas déclencher. Si un programme C++ tente d'ajouter un élément à un std::vector, il doit attendre que l'opération peut échouer en raison d'un manque de mémoire, mais un programme approprié à l'aide des well-written bibliothèques ne devrait pas être attendu pour traiter une violation d'accès.

Cette séparation est utile pour les programmeurs. Un violation d'accès est un problème grave : une écriture inattendue de la mémoire système critique peut affecter n'importe quel cadre du processus de façon imprévisible. Mais certaines erreurs SEH, comme une erreur de division-par-zéro résultant de l'entrée d'utilisateur incorrect et non contrôlé, sont moins graves. Si un programme avec une division par zéro est incorrect, il est peu probable que cela affecte toute autre partie du système. En fait, il est probable qu'un programme C++ peut gérer une erreur de division par zéro sans destabilizing le reste du système. Donc cette séparation est utile, il n'est pas tout à fait exprimer le besoin des programmeurs sémantique gérés.

Code géré et sur SEH

Le CLR est toujours livré exceptions SEH au code géré à l'aide des mêmes mécanismes comme des exceptions générées par le programme lui-même. Ce n'est pas un problème car code n'est pas tenter de gérer des conditions exceptionnelles il ne peut pas traiter raisonnablement. La plupart des programmes ne peut pas continuer en toute sécurité l'exécution après une violation d'accès. Malheureusement, le CLR exception Gestion des modèles a toujours conseillé aux utilisateurs d'intercepter ces erreurs graves en autorisant des programmes pour intercepter des exceptions en haut de la hiérarchie de System.Exception. Mais c'est rarement la bonne chose à faire.

Écriture catch (exception e) est une erreur programmation commune car les exceptions non gérées ont des conséquences graves. Mais vous pouvez dire que si vous ne connaissez pas les erreurs sont générées par une fonction, vous devez protéger contre toutes les erreurs possibles lorsque votre programme appelle cette fonction. Cela semble un cours raisonnable d'action jusqu'à ce que vous pensez que cela signifie poursuivre l'exécution lorsque le processus est peut-être dans un état endommagé. Parfois abandon du et essayez à nouveau sont la meilleure option : personne n'aime afficher une boîte de dialogue de Watson, mais il est préférable de redémarrer le programme que pour avoir des données endommagées.

Programmes d'interception des exceptions provenant de contextes qu'ils ne comprennent pas un problème grave. Mais vous ne pouvez pas résoudre le problème en utilisant les spécifications d'exceptions ou un autre mécanisme contrat. Et il est important que les programmes gérés soit capable de recevoir notification d'exceptions SEH car le CLR est une plate-forme pour plusieurs types d'applications et des hôtes. Certains hôtes, tels que SQL Server, devez disposer de total de contrôle du processus de leur application. Code géré qui interagit avec le code natif parfois doit traitent des exceptions C++ natives ou d'exceptions SEH.

Mais la plupart des programmeurs qui écrivent catch (exception e) n'est pas réellement détecter les violations d'accès. Ils pouvez préférer que l'exécution de son programme s'arrête lorsqu'une erreur irrémédiable se produit plutôt que de laisser le programme limp ainsi que dans un état inconnu. Cela est particulièrement vrai pour les programmes qui ordinateur hôte gérés compléments tels que Visual Studio ou Microsoft Office. Si une macro complémentaire provoque une violation d'accès et puis swallows l'exception, le ordinateur hôte peut faire endommager son propre état (ou fichiers de l'utilisateur) sans jamais réaliser le qu'opération a échoué.

Dans version 4 du CLR, l'équipe produit effectue des exceptions qui indiquent un état endommagé processus distincts de tous les autres exceptions. Nous sont désigner sur les exceptions SEH une douzaine pour indiquer l'état processus endommagé. La désignation concerne le contexte dans lequel l'exception est générée par opposition au type d'exception. Cela signifie qu'une violation d'accès provenant de Windows sera marqué comme une exception état endommagé (CSE), mais un générés dans le code d'utilisateur par écriture jeter que System.AccessViolation­Exception nouveau ne sont pas marquées comme étant un CSE. Si vous assisté 2008 contrôleur principal de domaine, vous avez reçu une communauté Technology Preview de Visual Studio 2010 qui inclut ces modifications.

Il est important de noter que l'exception n'est pas endommager le processus : l'exception est générée après que endommagement est détecté dans l'état du processus. Par exemple, lorsqu'une écriture par un pointeur de code unsafe fait référence mémoire qui n'appartient pas au programme, une violation d'accès est générée. L'écriture non autorisée n'a pas réellement se produire, le système d'exploitation activée propriétaire de la mémoire et a empêché l'action d'emplacement de prise de notes. La violation d'accès indique que le pointeur lui-même a été endommagé à une heure antérieure dans l'exécution de la thread.

Exceptions état endommagé

Dans la version 4 et versions ultérieure, le système d'exception CLR pas fournira CSE au code géré uniquement si le code a expressément informé qu'il peut gérer processus endommagé état exceptions. Cela signifie qu'une instance d'intercepter (exception e) dans le code géré n'est pas avoir le CSE présenté à elle. En apportant la modification à l'intérieur du CLR exception système vous ne devez modifier la hiérarchie d'exception ou de modifier exception n'importe quel langage géré gestion sémantique.

Pour des raisons de compatibilité, l'équipe CLR fournies quelques méthodes pour vous permettre d'exécuter votre ancien code sous l'ancien comportement :

  • Si vous souhaitez recompiler votre code créé dans Microsoft .NET Framework 3.5 et l'exécuter dans le 4.0 Framework .NET sans avoir à mettre à jour la source, vous pouvez ajouter une entrée dans votre fichier de configuration d'application : legacyCorruptedState­­ExceptionsPolicy = true.
  • Assemblys compilées avec .NET Framework 3.5 ou une version antérieure du runtime pourra traiter exceptions endommagé état (en d'autres termes, conserver l'ancien comportement) lorsque fonctionne sur la 4.0 Framework .NET.

Si vous souhaitez que votre code pour gérer le CSE, vous devez indiquer votre intention en activant la fonction contenant la clause d'exceptions (catch, finally, ou fault) avec un nouvel attribut : System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions. Si un CSE A est déclenché, le CLR effectuera sa recherche pour une clause catch correspondante mais seulement recherche dans les fonctions marquées avec l'attribut HandleProcessCorruptedStateExceptions (voir figure 2 ).

Figure 2 Utilisation HandleProcessCorruptedStateExceptions

// This program runs as part of an automated test system so you need
// to prevent the normal Unhandled Exception behavior (Watson dialog).
// Instead, print out any exceptions and exit with an error code.
[HandledProcessCorruptedStateExceptions]
public static int Main()
{
    try
    {
        // Catch any exceptions leaking out of the program
        CallMainProgramLoop();
    }
    catch (Exception e) // We could be catching anything here
    {
        // The exception we caught could have been a program error
        // or something much more serious. Regardless, we know that
        // something is not right. We'll just output the exception
        // and exit with an error. We won't try to do any work when 
        // the program or process is in an unknown state!
        System.Console.WriteLine(e.Message);
        return 1;
    }
    return 0;
  } 

Si une clause catch approprié est trouvée, le CLR dérouler la pile en tant que mais normal est uniquement exécuter Enfin et fault blocs (et en C#, le implicite enfin bloque d'une instruction) dans les fonctions marquées avec l'attribut. L'attribut HandleProcessCorruptedStateExceptions est ignoré lorsque dans code partiellement approuvé ou transparent car un ordinateur hôte approuvé ne voudriez pas qu'un non approuvé complément pour intercepter et ignorer ces exceptions graves.

Il est toujours incorrect utiliser réception (exception e)

Même si le système d'exception CLR marque les exceptions pires comme CSE, il est toujours pas judicieux d'écrire catch (exception e) dans votre code. Exceptions représentent une gamme de situations inattendues ensemble. Le CLR peut détecter les exceptions pires, exceptions SEH qui indiquent un état de processus peut-être endommagé. Mais autres conditions inattendues peuvent toujours être dangereuses s'ils sont ignorés ou traitement façon générique.

En l'absence d'altération de processus, le CLR propose quelques garanties sur la sécurité à l'exactitude et la mémoire programme assez forts. Lorsque vous exécutez un programme écrit dans le code MSIL (Microsoft Intermediate Language) sans Échec que vous pouvez être certain que toutes les instructions de votre programme exécute correctement. Mais faire dire à faire les instructions de programme est souvent différent de faire le programmeur souhaite. Un programme complètement correct conformément au CLR peut endommager état persistant, tels que les fichiers programme écrit sur un disque.

Prenez un exemple simple un programme qui gère une base de données des résultats de test pour une école élevé. Le programme utilise les principes de conception orientée objet pour encapsuler les données et génère des exceptions gérées à indiquer les événements inattendus. Un jour la secrétaire école rencontre la touche ENTRÉE une trop nombreuses fois lors de la génération un fichier de classe. Le programme essaie d'exécute pop d'une valeur d'une file d'attente vide et génère une QueueEmptyException qui va non gérée par les cadres sur la pile d'appels.

N'importe où dans la partie supérieure de la pile est une fonction, GenerateGrades(), avec une clause try/catch qui intercepte l'exception. Malheureusement, GenerateGrades() n'a aucune idée que les étudiants sont stockées dans une file d'attente et ne tout idée que faire avec un QueueEmpty­Exception. Mais le programmeur qui écrit GenerateGrades() n'est pas que le programme blocage sans enregistrer les données qui est jusqu'à présent été calculées. Tout est écrit en toute sécurité sur le disque et le programme se ferme.

Le problème avec ce programme est qu'elle rend un certain nombre de hypothèses qui peut être incorrect. Quelle est à dire que l'entrée manquante dans la file d'attente étudiant est à la fin ? Peut-être l'étudiant premier enregistrent got ignorée, ou le dixième. L'exception n'indique que le programmeur que le programme est incorrect. Prendre toute action, enregistrer les données sur disque ou de « récupération et poursuivre l'exécution, est repris son incorrect. Aucune action correcte n'est possible sans connaître le contexte dans lequel l'exception a été générée.

Si le programme a intercepté une exception spécifique proche à où l'exception a été générée, il peut-être en mesure de prendre l'action appropriée. Le programme connaît une QueueEmptyException signification de la fonction qui tente de dequeue aux participants. Si la fonction intercepte cette exception par type, plutôt que d'interception une classe entière de types d'exceptions — il trouveraient dans une position beaucoup mieux à essayez de rendre l'état du programme approprié.

En général, interception une exception spécifique est la chose correcte à faire car il fournit le contexte de la plupart à votre gestionnaire d'exceptions. Si votre code peut potentiellement intercepter deux exceptions, puis a pouvoir traiter les deux. Écriture de code indiquant catch (exception e) doit être en mesure de traiter littéralement les cas exceptionnels. C'est une promesse est très difficile à conserver.

Certaines langues essayez les programmeurs Empêcher l'interception d'une classe large d'exceptions. Par exemple, C++ a des caractéristiques d'exception, un mécanisme qui permet un programmeur indiquer les exceptions peuvent être déclenchées dans cette fonction. Java Ceci est une étape davantage avec exceptions vérifiées, une exigence compiler-enforced qu'une certaine classe d'exceptions est spécifié. Dans les deux langues, vous répertoriez les exceptions peuvent circuler hors de cette fonction dans la déclaration de fonction et appelants sont requise pour gérer ces exceptions. Spécifications d'exception sont judicieux, mais ils ont été mixte résultats dans les exercices pratiques.

Il existe un débat approfondie que pouvoir ou non n'importe quel code géré doit gérer CSE. Ces exceptions indiquent une erreur de niveau système normalement et doivent uniquement être gérées par code qui comprend le contexte de niveau système. Pendant que la plupart des gens ne devez pas la capacité à traiter CSE, il y a quelques scénarios où il est nécessaire.

Un scénario est lorsque vous êtes très proche de l'endroit où l'exception s'est produite. Par exemple, imaginez un programme qui appelle le code natif est connue pour être buggy. Débogage dans le code que vous apprenez qu'il zéros parfois un pointeur avant d'accéder à elle, qui provoque une violation d'accès. Vous souhaiterez peut-être utiliser l'attribut HandleProcessCorruptedStateExceptions sur la fonction qui appelle le code natif en utilisant P/Invoke, car vous connaissez la cause de l'altération de pointeur et que vous êtes à l'aise que l'intégrité du processus est conservée.

Le scénario peut appeler pour l'utilisation de cet attribut est lorsque vous êtes, ce que vous pouvez être de l'erreur. En fait, vous êtes presque prêt à quitter votre processus. Imaginons que vous avez écrit un ordinateur hôte ou une structure qui souhaite effectuer certains enregistrement personnalisé en cas d'une erreur. Vous pouvez placer votre principale fonction avec un bloc try/catch/finally et marquer avec HandleProcessCorruptedStateExceptions. Si une erreur inattendue rend les haut pour fonction principale de votre programme, vous écrire des données dans votre journal effectuant comme étant peu comme vous en avez à et quittez la procédure. Lorsque l'intégrité du processus est en question les modifications que vous y avez peuvent être dangereuse, mais si l'enregistrement personnalisé échoue parfois, il est acceptable.

Examinons le diagramme illustré figure 3 . Ici, fonction 1 (fn1()) est attribuée avec [HandleProcess­CorruptedStateExceptions] pour la clause catch intercepte la violation d'accès. Le enfin bloc de fonction 3 n'exécute pas même si l'exception est décelée dans la fonction 1. Fonction 4 en bas de la pile provoque une violation d'accès.

fig03.gif

La figure 3 exception et une violation d'accès

Il n'existe aucune garantie d'une des ces scénarios que vous effectuez est totalement sûr, mais il existe scénarios où simplement termine le processus est inacceptable. Toutefois, si vous souhaitez traiter un CSE il est un fardeau énorme sur votre en tant que le programmeur faire correctement. N'oubliez pas que le système d'exception CLR ne sont pas remettre même d'un CSE à toute fonction qui n'est pas marquée avec le nouvel attribut soit au cours de la première phase (lorsqu'il recherche une clause catch correspondante) ou de la phase deuxième (lorsqu'il unwinds état de chaque cadre et exécute Enfin et blocs de panne).

Le enfin bloc existe afin de garantir que le code toujours s'exécute, il existe une exception ou non. (Erreur blocs s'exécuter uniquement lorsqu'une exception se produit, mais ils ont une garantie similaire de toujours en cours d'exécution.) Ces constructions sont utilisées pour nettoyer les ressources critiques telles que relâcher les descripteurs de fichiers ou de renversement contextes d'emprunt d'identité.

Même code qui est écrit à fiable via l'utilisation de contrainte de l'exécution de zones (CER) ne sont pas être exécutées lorsqu'un CSE a été augmenté sauf s'il s'agit dans une fonction qui a été marquée avec l'attribut HandleProcessCorruptedStateExceptions. Il est très difficile d'écrire du code correct qui gère un CSE et continue d'exécuter le processus en toute sécurité.

Observez attentivement le code de la figure 4 pour voir ce qui peut accéder incorrect. Si ce code n'est pas dans une fonction qui peut traiter CSE, puis le enfin bloc ne s'exécutera lorsqu'une violation d'accès se produit pas. C'est bien si le processus se termine, le descripteur de fichier ouvert sera libéré. Mais si un autre code intercepte la violation d'accès et tente de restaurer l'état, il doit savoir qu'il a fermer ce fichier ainsi que de restaurer n'importe quel autre état externe que ce programme a été modifié.

La figure 4 le enfin bloc peut s'exécute pas

void ReadFile(int index)
    {
      System.IO.StreamReader file = 
        new System.IO.StreamReader(filepath);
          try
          {
            file.ReadBlock(buffer, index, buffer.Length);
          }
          catch (System.IO.IOException e)
          {
            Console.WriteLine("File Read Error!");
          }
          finally
          {
            if (file != null)
                {
                    file.Close()
                }
          }
    }

Si vous décidez que vous souhaitez traiter un CSE, votre code doit attendre qu'il y a une tonne de état critique qui n'a pas été déroulée. Enfin et blocs de panne n'ont pas été exécutés. Zones de l'exécution de contrainte n'ont pas été exécutées. Le programme et le processus, sont dans un état inconnu.

Si vous savez que votre code est adoptent l'attitude, vous savez que faire. Mais si vous n'êtes pas sûr de l'état de votre programme s'exécute dans, puis il est préférable de simplement laisser votre processus de quitter. Ou, si votre application est hébergée, invoquer la stratégie d'escalade que votre ordinateur hôte a spécifié. Voir Alessandro Catorcini et de Brian Grunkemeyer Colonne CLR Inside Out de décembre 2007 Pour plus d'informations sur l'écriture de code fiable et les zones CER.

Code intelligemment

Bien que le CLR vous empêche d'interception naively CSE, il est toujours pas judicieux d'attirer de trop nombreuses classes d'exceptions. Mais catch (exception e) apparaît dans beaucoup de code, et il est peu probable que ceci modifie. En fournissant ne pas exceptions qui représentent un état endommagé processus pour le code qui naively intercepte toutes les exceptions, vous empêchez ce code de rendre un pire situation grave.

La prochaine fois vous écrire ou maintenir code intercepte une exception, pensez à ce que signifie l'exception. Est le type détectés de correspondance votre programme (et les bibliothèques, qu'elle utilise) sont documentés de générer ? Savez-vous comment traiter l'exception telles que votre programme puisse correctement et en toute sécurité continuer l'exécution ?

Gestion des exceptions sont un outil puissant qui doit être utilisé avec précaution et thoughtfully. Si vous souhaitez vraiment utiliser cette fonctionnalité, si vous devez vraiment gérer les exceptions qui peuvent indiquer un processus endommagé, le CLR vous approuvez et vous permettent de faire. Simplement, soyez prudent et ce correctement.

Veuillez envoyer vos questions et commentaires à clrinout@microsoft.com.

Andrew Pardoe est un responsable de programme de CLR chez Microsoft. Il travaille sur plusieurs aspects du moteur d'exécution du Bureau et l'exécution de Silverlight. Vous pouvez le contacter à Andrew.Pardoe@Microsoft.com.