Pourquoi NullReferenceException ne contient-il pas d’informations sur ce qui est nul?

Quelle était la décision de conception derrière NullReferenceException ne contenant aucune information spécifique à l’exécution, à l’exception des données de classe de base (comme un stacktrace)? Et y a-t-il une extension pour Visual Studio qui peut vous dire immédiatement quelle partie d’une expression était nulle?

Un NRE est une exception de très bas niveau. Il s’agit d’une exception matérielle (un «piège») générée par le processeur lorsqu’il lui est demandé de lire des données à partir d’une adresse inférieure à 64 Ko. Cette région de l’espace de la mémoire virtuelle est toujours non mappée, en particulier pour piéger les bogues du pointeur. Il commence en tant que AccessViolation et est transformé en NRE par le CLR lorsque l’adresse est inférieure à 0x00010000. À ce stade, il existe très peu de contexte pour l’exception, tout ce qui est connu est l’adresse de l’instruction de code machine qui a provoqué l’interruption.

La rétro-ingénierie que cette instruction d’instruction de code machine renvoie à une variable nommée dans votre programme n’est pas possible. Il est important que cela fonctionne de cette façon, une gigue devrait générer un code très inefficace sinon. Tout ce qui peut être raisonnablement fait est de récupérer le numéro de ligne du code source. Cela nécessite des informations de débogage (un fichier .pdb) contenant des informations sur les numéros de ligne. Le CLR sait lire le fichier .pdb et l’utilise pour générer la trace de stack de l’exception. Cependant, cela rest souvent inexact en raison des optimisations effectuées par l’optimiseur JIT, qui déplace le code. Vous ne recevrez une correspondance garantie que pour la version Debug. La raison pour laquelle le PDB pour la version Release ne contient pas d’informations de numéro de ligne source. Vous pouvez changer cela.

Ce problème a une solution très simple. Vérifiez vous-même null et générez votre propre exception avant de laisser le runtime le faire. Le test est très bon marché, bien moins d’une nanoseconde.

Vous pouvez configurer Visual Studio de manière à ce qu’il soit NullReferenceException immédiatement pour NullReferenceException for NullReferenceException et non pas au bloc catch.

  • Déboguer
  • Des exceptions
  • Langue commune
  • Système d’exceptions à l’exécution
  • System.NullReferenceException (Cochez la case)

Ensuite, vous aurez une pause dans la ligne qui a causé l’ NullReferenceException .

Il n’y a pas de moyen sortingvial de déterminer ce qui était nul lors de l’exécution – les informations nécessaires devraient être décompilées et déduites de l’IL, ce qui est suffisamment bas pour que “l’élément en haut de la stack soit nul” “mais pas comment cet article est arrivé là.

(Et je ne connais pas une telle extension, mais ce serait une belle amélioration du débogueur )

NullReferenceException est lancé par le runtime, pas par le langage. Le runtime ne sait pas où la référence est venue; il sait juste qu’une instruction a essayé d’utiliser une référence nulle.

En fait, l’exception est “probablement” le résultat d’une exception SEH “violation d’access invalide” Windows native, qui est interceptée par le moteur d’exécution et convertie en exception IL (“probablement”: je n’ai pas vérifié si c’est le cas, mais Je pense à la façon la plus performante de JIT le code).

Toutes les informations sur votre code ne sont pas disponibles lors de l’exécution. Par exemple, les noms de variables locales ne sont pas disponibles. Donc, il est impossible de lancer une exception avec un message comme «la variable locale myObj est null, mais son membre a été appelé». De plus, il y a beaucoup d’objects écrits par l’utilisateur au moment de l’exécution (par exemple des classes, générés pour les fermetures / types anonymes / iterators, etc.) qui pourraient également être une source d’exceptions null-ref.

Si vous avez des symboles de débogage, vous pouvez suivre la ligne à l’origine de l’exception. Si c’est assez simple, vous obtiendrez directement votre valeur null . Sinon (pensez à a.Value = b.Do(c.GetX(),d.GetY(z.ToSsortingng())); ) vous devez déboguer avec votre IDE