Interruzione quando un valore cambia utilizzando il debugger di Visual Studio


198

C'è un modo per posizionare un watch su variabile e interrompere Visual Studio solo quando quel valore cambia?

Sarebbe molto più facile trovare problemi di stato difficili.

Può essere fatto?

Le condizioni di breakpoint necessitano ancora di un set di breakpoint, e preferirei impostare un watch e lasciare che Visual Studio imposti i breakpoint ai cambi di stato.


ma il punto di interruzione non influisce su nulla a meno che la condizione non sia valida, quindi puoi posizionare il punto di interruzione ovunque (come il setter) e portarlo da lì. Oppure mi sfugge qualcosa?
Oskar,

6
bene. è come il modo vb6 di debug. non ti interessa la posizione del punto di interruzione. basta aggiungere un'espressione condizionale per guardare la finestra e vb6 garantirà che si romperà ovunque si verifichi la condizione ..
Gulzar Nazim

scusate, non ho mai visto un modo, per quanto ne so il setter è la strada da percorrere
Oskar,

1
speravo di trovare notizie migliori; il vs2010 indica nessuna modifica msdn.microsoft.com/en-us/library/350dyxd0.aspx solo c ++ nativo ha questo @Scottgu che puoi fare di meglio!
gerryLowry,

Risposte:


134

Nel menu di Visual Studio 2005:

Debug -> Nuovo punto di interruzione -> Nuovo punto di interruzione dati

Accedere:

&myVariable

38
è disponibile per il codice gestito? Vedo questa opzione disabilitata per il progetto C #. Ricorda di aver letto da qualche parte questa è una funzione difficile da implementare nel debug delle app gestite soprattutto con il garbage collector coinvolto.
Gulzar Nazim,

27
Purtroppo è disponibile solo per il codice non gestito: msdn.microsoft.com/en-us/library/350dyxd0.aspx
Josh Kodroff,

17
È inoltre possibile convertire temporaneamente un campo in una proprietà e inserire un punto di interruzione sul getter o sul setter.
Jon Davis,

12
L'opzione "Data Breakpoint" in "Debug -> New Breakpoint" è disabilitata. Qualche idea sul perché? Rimane disabilitato sia che io sia effettivamente il debug o no. Sto usando Visual Studio 2015.
jbb

2
Un po 'in ritardo ma @jbb per me è abilitato solo quando mi sono fermato a un punto di interruzione durante il debug.
Allball103,

27

Puoi anche scegliere di rompere esplicitamente nel codice:

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

Da MSDN:

Debugger.Break: se non è collegato alcun debugger, agli utenti viene chiesto se desiderano collegare un debugger. In caso affermativo, il debugger viene avviato. Se è collegato un debugger, il debugger viene segnalato con un evento breakpoint utente e il debugger sospende l'esecuzione del processo come se fosse stato raggiunto un breakpoint debugger.

Questo è solo un fallback, però. L'impostazione di un breakpoint condizionale in Visual Studio, come descritto in altri commenti, è una scelta migliore.


2
FWIW, con modifica e continua preferisco farlo in questo modo: IME, i punti di interruzione condizionati sono sloooow
Mark Sowul,

Funziona - ma è molto doloroso - ho finito per fare qualcosa di simile - l'ho messo in cima a ogni metodo che sospettavo - e di nuovo in fondo (in una clausola finalmente) - in quel modo sapevo esattamente quale il metodo stava causando il problema - (cioè sapevo che i dati erano buoni prima di entrare nel metodo, e poi male prima di uscire).
BrainSlugs83,

26

Post davvero vecchio ma nel caso qualcuno non lo sappia ...

In Visual Studio 2015 , è possibile posizionare un punto di interruzione sull'accessorio setdi una proprietà implementata automaticamente e il debugger si interromperà quando la proprietà viene aggiornata

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

Aggiornare

In alternativa; @AbdulRaufMujahid ha sottolineato nei commenti che se la proprietà implementata automaticamente si trova su una singola riga, è possibile posizionare il cursore su get;o set;e premere F9e un punto di interruzione verrà posizionato di conseguenza. Bello!

public bool IsUpdated { get; set; }

5
Anche se la proprietà implementata automaticamente si trova su una riga, ad es. Stringa pubblica UserName {set; ottenere; }. L'utente può evidenziare getter o setter e premere F9 per aggiungere il punto di interruzione
Abdul Rauf

@AbdulRaufMujahid Awesome!
Craig,

13

Immagina di avere una classe chiamata A con la seguente dichiarazione.

class A  
{  
    public:  
        A();

    private:
        int m_value;
};

Volete fermare il programma quando qualcuno modifica il valore di "m_value".

Vai alla definizione della classe e metti un breakpoint nel costruttore di A.

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

Una volta interrotto il programma:

Debug -> Nuovo punto di interruzione -> Nuovo punto di interruzione dati ...

Indirizzo: & (this-> m_value)
Conteggio byte: 4 (Perché int ha 4 byte)

Ora, possiamo riprendere il programma. Il debugger si arresterà quando il valore viene modificato.

Puoi fare lo stesso con le classi ereditate o le classi composte.

class B
{
   private:
       A m_a;
};

Indirizzo: & (this-> m_a.m_value)

Se non si conosce il numero di byte della variabile che si desidera controllare, è possibile utilizzare l'operatore sizeof.

Per esempio:

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

Se guardi lo "Stack di chiamate" puoi vedere la funzione che ha cambiato il valore della variabile.


1
Quindi, cosa faresti esattamente se la cosa che sto cercando non fosse nelle mie lezioni? Ad esempio, sto cercando di scoprire esattamente dove viene abilitato o disabilitato un controllo? Posso aggiungere un controllo sul valore Abilitato del controllo durante il debug, certo, ma non c'è modo di romperlo in caso di modifica e quindi guardare dove si è fermato.
Nyerguds,

2
Se si tenta di eseguire il debug di una libreria esterna, è necessario compilare la libreria in modalità debug. Non ho familiarità con il componente, ma forse è possibile collegare un "callback" alla proprietà e inserire un punto di interruzione all'interno. Il modulo che descrivo ha bisogno dell'indirizzo di memoria, se non hai modo di conoscerlo, devi cercare altri metodi.
Momboco,

9

Modificare la variabile in una proprietà e aggiungere un punto di interruzione nel metodo set. Esempio:

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

    set { 
        m_var = value;
    }
}

3

Se stai usando WPF, c'è uno strumento fantastico: WPF Inspector .
Si collega a un'app WPF e visualizza l'intera struttura dei controlli con tutte le proprietà, e consente (tra le altre cose) di interrompere qualsiasi modifica di proprietà.

Ma purtroppo non ho trovato nessuno strumento che ti permettesse di fare lo stesso con QUALSIASI proprietà o variabile.



2

Fare clic con il tasto destro del mouse sul punto di interruzione funziona bene per me (anche se principalmente lo sto usando per punti di interruzione condizionali su valori variabili specifici. Anche l'interruzione di espressioni che coinvolgono un nome di thread funziona molto utile se si sta cercando di individuare problemi di threading).


2

Come scrisse Peter Mortensen:

Nel menu di Visual Studio 2005:

Debug -> Nuovo punto di interruzione -> Nuovo punto di interruzione dati

Immettere: & myVariable

Informazioni aggiuntive:

Ovviamente, il sistema deve sapere quale indirizzo in memoria guardare. Quindi - imposta un normale punto di interruzione sull'inizializzazione di myVariable(o myClass.m_Variable) - avvia il sistema e attendi fino a quando non si ferma a quel punto di interruzione. - Ora la voce di menu è abilitata e puoi guardare la variabile inserendo &myVariableo l'istanza inserendo&myClass.m_Variable . Ora gli indirizzi sono ben definiti.

Scusate quando ho fatto cose sbagliate spiegando una soluzione già fornita. Ma non ho potuto aggiungere un commento, e ci sono stati alcuni commenti a riguardo.


1

È possibile utilizzare un watchpoint di memoria nel codice non gestito. Non sono sicuro che siano disponibili nel codice gestito.


1

Probabilmente puoi fare un uso intelligente della funzione DebugBreak () .


Come esattamente? Eseguendo un thread separato in un ciclo stretto e invocando DebugBreak () ogni volta che si è verificata una modifica?
nalply

@nalpy Ad esempio, è possibile tracciare i luoghi in cui myVariableviene utilizzato e memorizzarne i valori dopo l'uso in una previousValuevariabile ausiliaria , quindi chiamare DebugBreak () quando myVariable!=previousValue; allora sapresti tra quali blocchi di codice myVariableè cambiato. Ma sono d'accordo che la soluzione di AShelly sia la migliore.
cancella il

1

Se lo si desidera, è possibile sovraccaricare l'operatore = per la variabile e posizionare il punto di interruzione all'interno della funzione di sovraccarico su una condizione specifica.


1

Aggiornamento nel 2019:

Questo è ora ufficialmente supportato in Visual Studio 2019 Preview 2 per .Net Core 3.0 o versione successiva. Naturalmente, potresti dover pensare ad alcuni rischi potenziali nell'utilizzo di una versione di anteprima di IDE. Immagino che nel prossimo futuro questo sarà incluso nel Visual Studio ufficiale.

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

Fortunatamente, i punti di interruzione dei dati non sono più un'esclusiva C ++ perché ora sono disponibili per .NET Core (3.0 o versione successiva) in Visual Studio 2019 Preview 2!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.