Si vous ouvrez cette fonction dans le débogueur, avec le code compilé en mode débogage:
bool foo(string arg)
{
return bar(arg);
}
Il y a 3 points de rupture que vous pouvez définir:
- A l'accolade d'ouverture de la fonction.
- Sur la ligne "retour".
- A l'accolade fermante de la fonction.
La définition d'un point d'arrêt sur l'accolade d'ouverture signifie "pause lorsque cette fonction est appelée". C'est pourquoi il existe une instruction no-op au début de la méthode. Lorsque le point d'arrêt est défini sur l'accolade ouvrante, le débogueur le définit réellement sur le no-op.
La définition d'un point de rupture sur l'accolade fermante signifie «pause lorsque cette fonction est désactivée». Pour que cela se produise, la fonction doit avoir une seule instruction de retour dans son IL, où le point de rupture peut être défini. Le compilateur permet que, en utilisant une variable temporaire pour stocker la valeur de retour, et la conversion
return retVal;
en
$retTmp = retVal;
goto exit;
puis injecter le code suivant au bas de la méthode:
exit:
return $ret;
En outre, en mode de débogage, les compilateurs sont stupides sur le code qu'ils génèrent.Ils font essentiellement quelque chose comme:
GenerateProlog();
foreach (var statement in statements)
{
Generate(statement);
}
GenerateEpilog();
Dans votre cas, vous voyez:
return foo(arg);
en cours de traduction en:
; //this is a no-op
bool retTemp = false;
retTemp = foo(arg);
goto exit;
exit:
return retTemp;
Si le compilateur a fait une "optimisation de la fenêtre coulissante" il pourrait être capable de regarder ce code et réaliser qu'il y avait une certaine redondance. Cependant, les compilateurs ne le font généralement pas en mode débogage. Les optimisations du compilateur peuvent faire des choses comme éliminer les variables et réorganiser les instructions, ce qui rend le débogage difficile. Le but d'une version de débogage étant d'activer le débogage, il ne serait pas bon d'activer les optimisations.
Dans une version de version, le code ne ressemblera pas à cela. C'est parce que le compilateur ne présente pas le code spécial pour permettre points d'arrêt sur les bretelles d'ouverture et de fermeture, ce qui laisse tout ce qui suit à compiler:
return bar(arg);
qui se termine à la recherche assez simple. Une chose à noter, cependant, est que je ne pense pas que le compilateur C# fasse beaucoup d'optimisations de fenêtres glissantes, même dans les versions commerciales. C'est parce que la plupart de ces optimisations dépendent de l'architecture du processeur sous-jacent et donc sont faites par le compilateur JIT. Faire les optimisations, même celles qui sont indépendantes du processeur, dans le compilateur C# peut empêcher le JIT d'optimiser le code (il cherche des modèles générés par une génération de code non optimisée, et s'il voit une IL fortement optimisée, il peut obtenir confus). Donc, les compilateurs de code généralement gérés ne le font pas. Il fait des "choses chères" (que le JIT ne veut pas faire à l'exécution), comme la détection de code mort, et l'analyse de variables en direct, mais elles n'abordent pas les problèmes résolus par l'optimisation de fenêtre glissante.
semble raisonnable pour moi –