Interrompre lorsqu'une valeur change à l'aide du débogueur Visual Studio

198

Existe-t-il un moyen de placer une surveillance sur une variable et de ne faire interrompre Visual Studio que lorsque cette valeur change?

Il serait ainsi beaucoup plus facile de trouver des problèmes d'état délicats.

Cela peut-il être fait?

Les conditions de point d'arrêt nécessitent toujours un ensemble de points d'arrêt, et je préfère définir une surveillance et laisser Visual Studio définir les points d'arrêt lors des changements d'état.

FlySwat
la source
mais le point d'arrêt n'affecte rien sauf si la condition se vérifie, vous pouvez donc placer votre point d'arrêt n'importe où (comme le Setter) et le prendre à partir de là. Ou est-ce que je manque quelque chose?
Oskar
6
bien. c'est comme la façon de déboguer vb6. vous ne vous souciez pas de l'emplacement du point d'arrêt. ajoutez simplement une expression conditionnelle à la fenêtre de surveillance et vb6 garantira qu'il se cassera partout où la condition est remplie ..
Gulzar Nazim
désolé, je n'ai jamais vu de chemin, pour autant que je sache, le passeur est le chemin à parcourir
Oskar
1
j'espérais trouver de meilleures nouvelles; le vs2010 indique aucun changement msdn.microsoft.com/en-us/library/350dyxd0.aspx seul c ++ natif a ce @Scottgu vous pouvez faire mieux!
gerryLowry

Réponses:

134

Dans le menu Visual Studio 2005:

Débogage -> Nouveau point d'arrêt -> Nouveau point d'arrêt des données

Entrer:

&myVariable
AShelly
la source
38
est-ce disponible pour le code managé? Je vois cette option désactivée pour le projet C #. N'oubliez pas de lire quelque part, c'est une fonctionnalité difficile à implémenter dans le débogage des applications gérées, en particulier avec le garbage collector impliqué.
Gulzar Nazim
27
Il n'est disponible que pour le code non managé
Josh Kodroff
17
Vous pouvez également convertir temporairement un champ en propriété et placer un point d'arrêt sur le getter ou le setter.
Jon Davis
12
L'option "Data Breakpoint" sous "Debug -> New Breakpoint" est désactivée .. une idée pourquoi? Il reste désactivé, que je débogue ou non. J'utilise Visual Studio 2015.
jbb
2
Un peu tard, mais @jbb pour moi, il n'est activé que lorsque je suis arrêté à un point d'arrêt pendant le débogage.
Allball103
27

Vous pouvez également choisir de rompre explicitement dans le code:

// Assuming C#
if (condition)
{
    System.Diagnostics.Debugger.Break();
}

Depuis MSDN:

Debugger.Break: si aucun débogueur n'est attaché, les utilisateurs sont invités à joindre un débogueur. Si oui, le débogueur est démarré. Si un débogueur est attaché, le débogueur est signalé par un événement de point d'arrêt utilisateur et le débogueur suspend l'exécution du processus comme si un point d'arrêt du débogueur avait été atteint.

Ce n'est qu'un repli, cependant. La définition d'un point d'arrêt conditionnel dans Visual Studio, comme décrit dans d'autres commentaires, est un meilleur choix.

Michael Petrotta
la source
2
FWIW, avec edit et continue, je préfère le faire de cette façon: IME, les points d'arrêt conditionnels sont lents
Mark Sowul
Cela fonctionne - mais c'est très douloureux - j'ai fini par faire quelque chose de similaire - je l'ai mis en haut de chaque méthode que je soupçonnais - et encore en bas (dans une clause enfin) - de cette façon, je savais exactement la méthode était à l'origine du problème - (c'est-à-dire que je savais que les données étaient bonnes avant d'entrer dans la méthode, puis mauvaises avant de la quitter).
BrainSlugs83
26

Vraiment un vieux message mais au cas où quelqu'un ne le sait pas ...

Dans Visual Studio 2015 , vous pouvez placer un point d'arrêt sur l' setaccesseur d'une propriété implémentée automatiquement et le débogueur s'arrêtera lorsque la propriété sera mise à jour

public bool IsUpdated
{
    get;
    set;    //set breakpoint on this line
}

Mettre à jour

Alternativement; @AbdulRaufMujahid a souligné dans les commentaires que si la propriété implémentée automatiquement se trouve sur une seule ligne, vous pouvez positionner votre curseur sur get;ou set;et frapper F9et un point d'arrêt sera placé en conséquence. Agréable!

public bool IsUpdated { get; set; }
Craig
la source
5
Même si la propriété implémentée automatiquement est sur une seule ligne, par exemple la chaîne publique UserName {set; avoir; }. L'utilisateur peut mettre en surbrillance getter ou setter et peut appuyer sur F9 pour ajouter un point d'arrêt
Abdul Rauf
@AbdulRaufMujahid Awesome!
Craig
13

Imaginez que vous ayez une classe appelée A avec la déclaration suivante.

class A  
{  
    public:  
        A();

    private:
        int m_value;
};

Vous souhaitez que le programme s'arrête lorsque quelqu'un modifie la valeur de "m_value".

Accédez à la définition de classe et mettez un point d'arrêt dans le constructeur de A.

A::A()
{
    ... // set breakpoint here
}

Une fois que nous avons arrêté le programme:

Débogage -> Nouveau point d'arrêt -> Nouveau point d'arrêt des données ...

Adresse: & (this-> m_value)
Nombre d'octets: 4 (car int a 4 octets)

Maintenant, nous pouvons reprendre le programme. Le débogueur s'arrête lorsque la valeur est modifiée.

Vous pouvez faire de même avec les classes héritées ou les classes composées.

class B
{
   private:
       A m_a;
};

Adresse: & (this-> m_a.m_value)

Si vous ne connaissez pas le nombre d'octets de la variable que vous souhaitez inspecter, vous pouvez utiliser l'opérateur sizeof.

Par exemple:

// to know the size of the word processor,  
// if you want to inspect a pointer.
int wordTam = sizeof (void* ); 

Si vous regardez la "pile d'appels", vous pouvez voir la fonction qui a changé la valeur de la variable.

momboco
la source
1
Alors, que feriez-vous exactement si la chose que je recherche n'est pas dans mes propres cours? Comme, par exemple, j'essaie de savoir exactement où un contrôle est activé ou désactivé? Je peux ajouter une surveillance sur la valeur Enabled du contrôle pendant le débogage, bien sûr, mais il n'y a aucun moyen de le faire interrompre lors du changement et de regarder où il s'est arrêté.
Nyerguds
2
Si vous essayez de déboguer une bibliothèque externe, vous aurez besoin de la bibliothèque compilée en mode débogage. Je ne suis pas familiarisé avec le composant, mais vous pouvez peut-être connecter un "rappel" à la propriété et mettre un point d'arrêt à l'intérieur. Le formulaire que je décris a besoin de l'adresse mémoire, si vous n'avez aucun moyen de le savoir, il faut rechercher d'autres méthodes.
momboco
9

Modifiez la variable en propriété et ajoutez un point d'arrêt dans la méthode set. Exemple:

private bool m_Var = false;
protected bool var
{
    get { 
        return m_var;
    }

    set { 
        m_var = value;
    }
}
Marcello
la source
3

Si vous utilisez WPF, il existe un outil génial: WPF Inspector .
Il s'attache à une application WPF et affiche l'arborescence complète des contrôles avec toutes les propriétés, et il vous permet (entre autres) d'interrompre tout changement de propriété.

Mais malheureusement, je n'ai trouvé aucun outil qui vous permettrait de faire de même avec n'importe quelle propriété ou variable.

Julien N
la source
2

Le clic droit sur le point d'arrêt fonctionne bien pour moi (bien que la plupart du temps je l'utilise pour des points d'arrêt conditionnels sur des valeurs de variable spécifiques.

Oskar
la source
2

Comme l'a écrit Peter Mortensen:

Dans le menu Visual Studio 2005:

Débogage -> Nouveau point d'arrêt -> Nouveau point d'arrêt des données

Entrez: & myVariable

Information additionnelle:

De toute évidence, le système doit savoir quelle adresse en mémoire regarder. Donc - définissez un point d'arrêt normal pour l'initialisation demyVariable (ou myClass.m_Variable) - exécutez le système et attendez qu'il s'arrête à ce point d'arrêt. - Maintenant, l'entrée de menu est activée, et vous pouvez regarder la variable en entrant &myVariable, ou l'instance en entrant &myClass.m_Variable. Maintenant, les adresses sont bien définies.

Désolé quand j'ai mal fait en expliquant une solution déjà donnée. Mais je n'ai pas pu ajouter de commentaire, et il y a eu des commentaires à ce sujet.

R Risack
la source
1

Vous pouvez utiliser un point d'observation de la mémoire dans du code non managé. Je ne sais pas si ceux-ci sont disponibles dans le code managé.

1800 INFORMATION
la source
1

Vous pouvez probablement faire un usage intelligent de la fonction DebugBreak () .

essuyer
la source
De quelle façon précisément? En exécutant un thread séparé dans une boucle étroite et en invoquant DebugBreak () chaque fois qu'un changement a été rencontré?
nalply
@nalpy Vous pouvez par exemple tracer les endroits où myVariableest utilisé et stocker ses valeurs après utilisation dans une previousValuevariable auxiliaire , puis appeler DebugBreak () quand myVariable!=previousValue; alors vous saurez entre quels blocs de code myVariablea changé. Mais je suis d'accord que la solution d'AShelly est la meilleure.
essuyez
1

Vous pouvez éventuellement surcharger l'opérateur = pour la variable et mettre le point d'arrêt à l'intérieur de la fonction surchargée dans des conditions spécifiques.

PREMIER
la source
1

Mise à jour en 2019:

Ceci est désormais officiellement pris en charge dans Visual Studio 2019 Preview 2 pour .Net Core 3.0 ou supérieur. Bien sûr, vous devrez peut-être réfléchir à certains risques potentiels liés à l'utilisation d'une version d'aperçu d'IDE. J'imagine que dans un proche avenir, cela sera inclus dans le Visual Studio officiel.

https://blogs.msdn.microsoft.com/visualstudio/2019/02/12/break-when-value-changes-data-breakpoints-for-net-core-in-visual-studio-2019/

Heureusement, les points d'arrêt de données ne sont plus une exclusivité C ++ car ils sont désormais disponibles pour .NET Core (3.0 ou supérieur) dans Visual Studio 2019 Preview 2!

Mat
la source