Puis-je connaître la valeur de retour avant de revenir lors du débogage dans Visual Studio?

387

Prenez la fonction suivante:

DataTable go() {
    return someTableAdapter.getSomeData();
}

Lorsque je définit un point d'arrêt dans cette fonction, y a-t-il une possibilité d'inspecter la valeur retournée? go()est directement couplé à une grille de données dans une .aspxpage.

La seule façon d'inspecter la table de données retournée est d'utiliser une variable temporaire. Cependant, c'est un peu gênant. N'y a-t-il pas une autre façon?

doekman
la source
1
Vous pouvez ajouter une montre si vous remontez dans la pile des appels
Chris S
Vous étiez capable de faire cela dans VB6, je me souviens. Mais à l'époque, la syntaxe des fonctions impliquait de définir la valeur de la fonction sur la valeur de retour ...
Neil Barnwell
5
Commentaire pour les utilisateurs de Visual C ++: Tapez $ ReturnValue dans la fenêtre immédiate ou la fenêtre de surveillance. Au moins sur mon VS 2010 ça a marché!
sergiol
9
Pour VS2015, utilisez $ ReturnValue1 .. au cas où vous ne voudriez pas lire les 20 réponses et 100 commentaires ci-dessous!
felickz
3
Quelle est la réponse 2019 à tout cela? Ces réponses sont super datées.
dylanh724

Réponses:

265

Pas que je sache de. Notez que si vous faites ajouter une variable, il va être supprimée par le compilateur dans la version construit de toute façon ...

Mise à jour: cette fonctionnalité a été ajoutée à VS2013 . Vous pouvez voir les valeurs de retour dans les fenêtres d'autos ou utiliser $ReturnValuedans la fenêtre de surveillance / immédiate.

La valeur ne peut être vue directement qu'après le retour de la fonction, donc le moyen le plus simple d'y accéder est de mettre un point d'arrêt sur l'appel de fonction et de passer (F10) l'appel.


Mise à jour pour VS2015: boo! malheureusement, il ne semble pas être dans la mise à jour VS2015 (devenv v14)
pour VS2017: il est de retour. (devenv v15)

Marc Gravell
la source
12
La raison de renoncer à la température est la lisibilité et le style, pas l'efficacité, non?
orip
2
@orip il y a plusieurs raisons de ne pas modifier le code, telles que; ce n'est pas votre code, c'est un débogage ponctuel et une nouvelle étape prendra du temps. (c'est pourquoi j'ai quand même cherché cette question :-)
Myster
8
C'est possible depuis VS 2010 avec IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth
3
@MarcGravell Votre réponse est fausse ! Bien sûr, il m'a fallu six ans entre votre réponse et la sortie de MS de cette fonctionnalité dans VS13, mais quand même. Si vous souhaitez n'aviez ajouté « pour le moment » comme un avertissement ... (Non, je ne suis pas attardé Il. Est une blague, bien sûr que vous êtes godlike, mon pote..)
Konrad Viltersten
6
@MarcGravell pour VS2015: $ ReturnValue1 fonctionne! (testé dans la version ultime)
GY
58

Cela peut être fait dans Visual Studio 2013 avec CLR 4.5.1 selon le site de commentaires des clients . Il n'était pas disponible dans les versions précédentes pour C #.

(Visual Studio 2008 et versions antérieures l'ont pris en charge pour VB.NET. Il a toujours été disponible pour les développeurs C / C ++.)

Alex Angas
la source
1
Comment procédez-vous dans Visual Studio 2010 C ++?
Utilisateur
Microsoft Connect indique qu'il existe un problème fondamental avec le code managé qui empêche de l'implémenter de manière fiable:
Dan Solovay
@DanSolovay Les mots qu'ils utilisent sont "nous ne pourrions pas toujours faire la bonne chose" (pour VS11) mais ils "veulent ramener cela" et "recherchent un certain nombre de solutions potentielles à ce problème".
Alex Angas
L'entrée de connexion est périmée. La fonctionnalité semble être ... abandonnée: (((
Softlion
1
C'est possible depuis VS 2010 avec IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth
25

Je suis d'accord que c'est une chose très utile à avoir: non seulement voir la valeur de retour de la méthode avant d'en sortir, mais aussi voir la valeur de retour des méthodes que je viens de franchir. Je l'ai implémenté dans le cadre d'une extension commerciale de Visual Studio appelée " OzCode ".

Avec lui, vous pouvez afficher les valeurs de retour de méthode directement sur l'éditeur de code, comme une sorte d'affichage HUD:

Visualisation des instructions

Pour plus d'informations, veuillez voir cette vidéo .

Omer Raviv
la source
23

Selon Microsoft, il n'y a aucun moyen de l'implémenter de manière fiable avec du code managé. C'est un problème qu'ils connaissent et sur lequel ils travaillent:

Pour ceux qui ont de l'expérience dans le débogage de code C ++ ou VB6 natif, vous avez peut-être utilisé une fonctionnalité dans laquelle des valeurs de retour de fonction vous sont fournies dans la fenêtre Autos. Malheureusement, cette fonctionnalité n'existe pas pour le code managé. Bien que vous puissiez contourner ce problème en affectant les valeurs de retour à une variable locale, ce n'est pas aussi pratique car cela nécessite de modifier votre code. Dans le code managé, il est beaucoup plus difficile de déterminer la valeur de retour d'une fonction que vous avez franchie. Nous avons réalisé que nous ne pouvions pas faire la bonne chose de manière cohérente ici et nous avons donc supprimé la fonctionnalité plutôt que de vous donner des résultats incorrects dans le débogueur. Cependant, nous voulons vous le ramener et nos équipes CLR et Debugger recherchent un certain nombre de solutions potentielles à ce problème. Malheureusement, cela ne fera pas partie de Visual Studio 11.

https://connect.microsoft.com/VisualStudio/feedback/details/597933/add-a-return-pseudo-variable-to-the-visual-studio-debugger-for-net-code

Dan Solovay
la source
1
Par @Alex ci-dessus ( stackoverflow.com/a/3714884/402949 ), ceci est disponible pour VS2013 avec CLR 4.5
Dan Solovay
21

Concernant Visual Studio 2015:

Selon la réponse actuellement acceptée par Marc Gravell:

Cette fonctionnalité a été ajoutée à Visual Studio 2013 . Vous pouvez voir les valeurs de retour dans les fenêtres d'autos ou utiliser $ ReturnValue dans la fenêtre de surveillance / immédiate

Cette réponse indiquait également que cette fonctionnalité ne fonctionne pas dans Visual Studio 2015. Ce n'est pas (entièrement) vrai. Sur Examiner les valeurs de retour des appels de méthode, il y a la note suivante:

Les évaluateurs d'expressions héritées doivent être activés pour que $ ReturnValue soit reconnu (Outils / Options / Débogage / Utiliser les évaluateurs d'expressions C # et VB hérités ). Sinon, vous pouvez utiliser $ ReturnValue1 .

J'ai testé cela dans Visual Studio 2015 Enterprise:

  • Avec les évaluateurs d'expressions héritées désactivés: seul $ ReturnValue1 fonctionne
  • Avec les évaluateurs d'expression existants activés: à la fois ReturnValue $ et ReturnValue1 $ travail
PascalK
la source
3
Cela ne semble plus nécessaire. Sur VS 2015 Update 3, les évaluateurs hérités sont désactivés et $ReturnValuefonctionnent. Cependant, la valeur de retour n'apparaît nulle part si l' Use managed compatibility modeoption de débogage est activée.
Nick
13

Si vous allez dans le menu OutilsOptions , IntelliTrace et modifiez le paramètre pour collecter les événements et les informations d'appel.

Vous pouvez revenir à l'événement d'appel précédent ( Ctrl+ Shift+ F11) et voir la valeur temporaire renvoyée par l'appel de méthode dans la fenêtre Autos en tant qu'enfant du nom de la méthode.

Cela ne vous montre pas la valeur de retour pour la méthode dans laquelle vous vous trouvez. Il vous montre juste la valeur de retour de la dernière méthode appelée dans la méthode actuelle.

Donc c'est bon pour

DataTable go(){return someTableAdapter.getSomeData();}

car il vous montre la valeur de retour pour someTableAdapter.getSomeData().

Mais pas pour:

int go(){return 100 * 99;}
Ross Buggins
la source
12

Vieille astuce des jours pré .NET: Ouvrez la fenêtre Registres et regardez la valeur du registre EAX. Celui-ci contient la valeur de retour de la dernière fonction appelée.

ColinM
la source
1
+1 pour la vieille école plus proche de l'approche métal - cela ne fonctionnera cependant pas pour toutes les valeurs de retour (et cela dépend du JIT'er, évidemment - qui sait quelle optimisation folle il pourrait décider de ne pas utiliser EAX? ). Pour les types intégraux, cela fonctionnera (principalement?). Les types de grande valeur sont une question différente (et pour autant que je me souvienne d'un article de blog, ceux-ci ne seront pas affichés dans VS2013 non plus).
JimmiTh
10

Sortez de la méthode go () en utilisant Shift-F11, puis dans la fenêtre de débogage "Autos", il affichera la valeur de retour de l'appel de méthode qui vient de sortir de la pile (dans ce cas, la méthode go () qui est ce que tu veux). Il s'agit du comportement dans Visual Studio 2005; Je n'ai pas utilisé Visual Studio 2008, donc je ne sais pas si cela se comporte de la même manière dans cette version.

LeopardSkinPillBoxHat
la source
J'ai essayé cela dans VS2005 et VS2008, mais je ne le vois pas vraiment. J'ai la fenêtre "Autos" ouverte, mais quand dans la fonction "go", la fenêtre autos est juste vide. Également lors de la sortie de la fonction (l'accolade fermante de la fonction est jaune). Pouvez-vous me donner un indice supplémentaire?
doekman
Je m'attendrais à ce que la fenêtre Autos soit vide tandis qu'à l'intérieur de la fonction go (). Vous devez sortir COMPLÈTEMENT de la fonction (c'est-à-dire que le curseur de débogage doit pointer vers la fonction qui a APPELÉ go ()), puis vous devriez voir la valeur de retour de go () dans la fenêtre Autos.
LeopardSkinPillBoxHat
@LeopardSkinPillBoxHat: ne peut pas faire fonctionner cela, même avec votre indice supplémentaire. Essayez-vous cela dans Visual Basic? Il semble avoir un meilleur support pour observer et changer les valeurs de retour ...
Roman Starkov
@romkyns - Qu'est-ce qui apparaît dans la fenêtre "Autos" pour vous? N'affiche-t-il pas une ligne indiquant ce que la dernière fonction appelée a renvoyé?
LeopardSkinPillBoxHat
2
@LeopardSkinPillBoxHat: non, ça ne fait pas ça en C #. PS Wow, il m'a fallu un certain temps pour revoir cela.
Roman Starkov
7

Oui, il y a un très bon moyen. Un inconvénient majeur est qu'il faudrait attendre 5, voire 6 ans. Depuis que je vois que vous avez posté en novembre 2008, je vous suggère de waaaaaa ...

... aaaait. Et voilà! Pour vous, MS a publié la dernière version de Visual Studio 2013, où il s'agit d'une fonctionnalité par défaut accessible à partir des menus lors de l'exécution en mode débogage (menu DebugWindowsAutos ).

Konrad Viltersten
la source
@Doug Parce que la question a été posée en novembre 2008 et ma réponse est venue en septembre 2014. L'affiche originale est probablement satisfaite et ne veut pas déplacer le crédit. Mais je suis d'accord avec vous - je ne verrais pas d'inconvénient à ce que je répète quelques réponses. J'aime les upsies et les gains de répétition. :)
Konrad Viltersten
Eu ce problème aujourd'hui. Merci d'avoir répondu en 2014 même si le numéro initial est de 2008. Votre réponse est ce que je cherchais.
AP
@AP Aucun problème. On se sent un peu comme une machine à remonter le temps pour voir ce post. Le souffle du passé, hehe.
Konrad Viltersten
5

Il existe de nombreuses solutions de contournement, mais aucune ne semble satisfaisante.

Pour citer John Skeet ci-dessous (commentaire sur une réponse maintenant supprimée):

Cela me semble toujours gênant, surtout si vous ne savez pas de quelle valeur de retour vous aurez besoin avant de commencer le débogage. Je ne veux vraiment pas avoir une variable temporaire encombrant mon code chaque fois que je retourne quoi que ce soit.

En théorie, le débogueur pourrait avoir une returnvariable. Après tout: c'est juste une variable sur la pile:

unsafe {
  int * sp = stackalloc int[1];
  try {
    return a+b;
  }
  finally {
    Trace.WriteLine("return is " + *(sp+3));
  }
}

Considérez donc cela comme une demande de fonctionnalité pour Visual Studio.

doekman
la source
il y a une grande différence entre une variable (un local bien défini) et une valeur sur la pile. C'est une valeur sur la pile, mais ce n'est pas une variable (= locale).
Marc Gravell
@Marc: Je ne sais pas comment fonctionne le CLR, mais de nombreux compilateurs placent des arguments de fonction sur la pile en dessous du pointeur de pile (sp) et des variables locales sur la pile, au-dessus du pointeur de pile. C'est exactement ce que j'essaie de montrer. Et OK, lorsque la valeur de retour est un type de référence, vous obtenez simplement une valeur de pointeur.
doekman
1
Ce n'est pas nécessairement sur la pile. En fait, si vous affichez Debug -> Registers, vous êtes susceptible de le voir dans EAX
Mark Sowul
5

Je voulais développer la réponse de PascalK pour que cela fonctionne dans Visual Studio 2015, car il existe une fonctionnalité cachée qui n'est pas documentée dans Examiner les valeurs de retour des appels de méthode .

Si vous avez des appels de fonction imbriqués, les pseudo-variables $ResultValueXsont automatiquement créées, où le X fait référence à l'ordre des appels de fonction. Donc, si vous avez un appel tel que Multiply(Five(), Six()), les pseudo-variables suivantes sont créées:

Five()     | $ResultValue1 = 5
Six()      | $ResultValue2 = 6
Multiply() | $ResultValue3 = 30
splttingatms
la source
2

Microsoft Visual C ++ le faisait auparavant, mais Visual Studio ne fonctionne pas AFAIK .. :(

Sprintstar
la source
2

La seule façon que je sache est de placer un point d'arrêt sur la ligne de retour, puis d'appeler la fenêtre Quick Watch et d'entrer l'expression retournée:

someTableAdapter.getSomeData();

Mais cela ne fonctionne que si l'appel ne change pas l'état d'un objet (car il y aura un deuxième appel à la même méthode lorsque vous reprendrez l'exécution).

Sylvain Rodrigue
la source
5
Cela ne fonctionne également que si votre expression n'a pas de lambdas.
Roman Starkov
1

Vous pouvez également demander d'évaluer la valeur dans la fenêtre intermédiaire, si elle ne définit pas d'indicateurs ou d'autres variables, mais ne renvoie que quelque chose.

Biri
la source
Vous devez inclure le lambda dans la question, car j'utilise aussi la fenêtre immédiate parfois
Chris S
1

Je pense que vous pouvez le déterminer en regardant le registre RAX dans la fenêtre Registers (Debug / Windows / Registers). Après avoir quitté (SHIFT + F11) de la fonction, vérifiez le registre RAX. Je ne sais pas pour un fait, mais une fois sur une lune, vous pouvez vérifier un registre (avant les jours .NET) et y voir la valeur de retour. Il peut même s'agir d'une combinaison de RAX et RBX, etc.

Joe Rattz
la source
1

L'ouverture de la fenêtre Débogage → Autos vous permet de fermer. Il ne montrera pas la valeur de retour réelle, mais il montrera ce qui a été évalué dans l'instruction de retour.

GeekyMonkey
la source
2
Impossible d'obtenir la fenêtre d'autos VS2008 pour montrer quelque chose comme ça. Pourriez-vous clarifier?
Roman Starkov,
return x + y; Ce que je voulais dire, c'est que si vous définissez un point d'arrêt sur cette ligne, votre fenêtre Debug-Autos affichera les valeurs actuelles de x et y. Comme je l'ai dit, cela ne fait que vous rapprocher. J'essaie seulement d'aider. Je ne pense pas que cela mérite un downvote.
GeekyMonkey
1

Oui, en passant à VB.NET. ; P (Vous venez de dire "Visual Studio".;)

Aussi longtemps que je me souvienne (de Visual Basic à toutes les versions de VB.NET), vous pouvez simplement interroger le nom de la fonction. Il "fonctionne" comme une variable locale qui est implicitement déclarée au début de la fonction et sa valeur actuelle est également utilisée comme valeur de retour chaque fois que la fonction se termine via des moyens de déclaration non-retour (c'est-à-direExit Function -à- ou simplement en traversant) et bien sûr, lorsque l'instruction return est utilisée.

Il est également défini sur l'expression de l'instruction return. Tout comme une variable locale, sa valeur peut être inspectée à n'importe quel point d'exécution à l'intérieur de la fonction (y compris après l'exécution de l'instruction return). C # n'a pas cela et devrait.

Cette petite fonctionnalité VB.NET (plus la Exit Functiondéclaration qu'elle active - une autre fonctionnalité que C # n'a pas et devrait) est très utile dans une forme de programmation défensive que je pratique où j'initialise toujours le nom de la fonction à la valeur d'échec / par défaut comme première déclaration. Ensuite, à n'importe quel point d'échec (qui se produit normalement beaucoup plus souvent que les points de réussite), je peux simplement appeler l' Exit Functioninstruction (c'est-à-dire sans avoir à dupliquer l'expression d'échec / par défaut ou même un nom de constante / variable).

À M
la source
1

La réponse acceptée ne fonctionne pas correctement avec Visual Studio 2015, mais en plaçant un point d'arrêt sur la dernière ligne de la méthode et en appuyant sur F10, elle mettra toutes les expressions de la valeur de retour dans la fenêtre locale.

Esben Skov Pedersen
la source
Vous pouvez également modifier la réponse acceptée pour inclure vos commentaires.
doekman
0

Vous pouvez essayer de sélectionner "someTableAdapter.getSomeData();", faire un clic droit dessus et opter pour Quick Watch .

Yann Semet
la source
-1

Faites glisser et déposez l'expression de retour dans une fenêtre de surveillance.

Par exemple, dans la déclaration

return someTableAdapter.getSomeData();

glisser déposer

someTableAdapter.getSomeData()

dans une fenêtre de surveillance, et vous verrez la valeur.

Vous pouvez le faire pour n'importe quelle expression.

Pita.O
la source
2
Le problème avec ça: l'expression est évaluée deux fois.
doekman
6
Et les expressions watch ne peuvent pas contenir d'expressions lambda, que j'utilise un peu.
Steve Crane