Romper cuando un valor cambia usando el depurador de Visual Studio

198

¿Hay alguna manera de colocar un reloj en la variable y solo hacer que Visual Studio se rompa cuando ese valor cambia?

Haría mucho más fácil encontrar problemas de estado difíciles.

Se puede hacer esto?

Las condiciones de punto de interrupción todavía necesitan un conjunto de puntos de interrupción, y prefiero establecer un reloj y dejar que Visual Studio establezca los puntos de interrupción en los cambios de estado.

FlySwat
fuente
pero el punto de interrupción no afecta nada a menos que la condición se mantenga, por lo que puede colocar su punto de interrupción en cualquier lugar (como el Setter) y tomarlo desde allí. ¿O me estoy perdiendo algo?
Oskar
66
bien. Es como la forma vb6 de depuración. no te importa la ubicación del punto de interrupción. simplemente agregue una expresión condicional para mirar la ventana y vb6 garantizará que se romperá donde se cumpla la condición ..
Gulzar Nazim
lo siento, nunca he visto un camino, que yo sepa, el acomodador es el camino a seguir
Oskar
1
esperaba encontrar mejores noticias; el vs2010 indica que no hay cambios msdn.microsoft.com/en-us/library/350dyxd0.aspx ¡ solo c ++ nativo tiene este @Scottgu que puede mejorar!
gerryLowry

Respuestas:

134

En el menú de Visual Studio 2005:

Depuración -> Nuevo punto de interrupción -> Nuevo punto de interrupción de datos

Entrar:

&myVariable
AShelly
fuente
38
¿Está esto disponible para el código administrado? Veo esta opción deshabilitada para el proyecto C #. Recuerde leer en alguna parte, esta es una característica difícil de implementar en la depuración de aplicaciones administradas, especialmente con el recolector de basura involucrado.
Gulzar Nazim
27
Desafortunadamente, solo está disponible para código no administrado: msdn.microsoft.com/en-us/library/350dyxd0.aspx
Josh Kodroff el
17
También puede convertir temporalmente un campo en una propiedad y poner un punto de interrupción en el captador o definidor.
Jon Davis
12
La opción "Punto de interrupción de datos" en "Depurar -> Nuevo punto de interrupción" está desactivada. ¿Alguna idea de por qué? Permanece deshabilitado si o no, en realidad estoy depurando o no. Estoy usando Visual Studio 2015.
jbb
2
Un poco tarde, pero @jbb para mí solo está habilitado cuando me detengo en un punto de interrupción durante la depuración.
Allball103
27

También puede optar por romper explícitamente en el código:

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

De MSDN:

Debugger.Break: si no se adjunta ningún depurador, se pregunta a los usuarios si desean adjuntar un depurador. En caso afirmativo, se inicia el depurador. Si se adjunta un depurador, el depurador se señala con un evento de punto de interrupción del usuario, y el depurador suspende la ejecución del proceso como si se hubiera alcanzado un punto de interrupción del depurador.

Sin embargo, esto es solo una alternativa. Establecer un punto de interrupción condicional en Visual Studio, como se describe en otros comentarios, es una mejor opción.

Michael Petrotta
fuente
2
FWIW, con editar y continuar, prefiero hacerlo de esta manera: IME, los puntos de interrupción condicionales son lentos
Mark Sowul
Esto funciona, pero es muy doloroso, terminé haciendo algo similar: puse esto en la parte superior de cada método que sospechaba, y nuevamente en la parte inferior (en una cláusula final), de esa manera supe exactamente qué el método estaba causando el problema (es decir, sabía que los datos eran buenos antes de ingresar al método y luego malos antes de salir).
BrainSlugs83
26

Publicación muy antigua pero en caso de que alguien no se dé cuenta ...

En Visual Studio 2015 , puede colocar un punto de interrupción en el setdescriptor de acceso de una propiedad implementada automáticamente y el depurador se interrumpirá cuando se actualice la propiedad

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

Actualizar

Alternativamente; @AbdulRaufMujahid ha señalado en los comentarios que si la propiedad implementada automáticamente está en una sola línea, puede colocar el cursor en get;o set;y presionar F9y se colocará un punto de interrupción en consecuencia. ¡Agradable!

public bool IsUpdated { get; set; }
Craig
fuente
55
Incluso si la propiedad implementada automáticamente está en una línea, por ejemplo, una cadena pública UserName {set; obtener; }. El usuario puede resaltar getter o setter y puede presionar F9 para agregar un punto de interrupción
Abdul Rauf
@AbdulRaufMujahid ¡Impresionante!
Craig
13

Imagine que tiene una clase llamada A con la siguiente declaración.

class A  
{  
    public:  
        A();

    private:
        int m_value;
};

Desea que el programa se detenga cuando alguien modifique el valor de "m_value".

Vaya a la definición de clase y ponga un punto de interrupción en el constructor de A.

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

Una vez que detuvimos el programa:

Depuración -> Nuevo punto de interrupción -> Nuevo punto de interrupción de datos ...

Dirección: & (this-> m_value)
Recuento de bytes: 4 (porque int tiene 4 bytes)

Ahora, podemos reanudar el programa. El depurador se detendrá cuando se cambie el valor.

Puede hacer lo mismo con clases heredadas o clases compuestas.

class B
{
   private:
       A m_a;
};

Dirección: & (this-> m_a.m_value)

Si no conoce el número de bytes de la variable que desea inspeccionar, puede usar el operador sizeof.

Por ejemplo:

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

Si observa la "Pila de llamadas", puede ver la función que cambió el valor de la variable.

momboco
fuente
1
Entonces, ¿qué harías exactamente si lo que estoy buscando no está en mis propias clases? Por ejemplo, ¿estoy tratando de averiguar exactamente dónde se habilita o deshabilita un control? Puedo agregar un reloj al valor Habilitado del control durante la depuración, claro, pero no hay forma de hacer que se rompa con el cambio y luego mirar dónde se detuvo.
Nyerguds
2
Si intenta depurar una biblioteca externa, necesitaría la biblioteca compilada en modo de depuración. No estoy familiarizado con el componente, pero tal vez pueda conectar una "devolución de llamada" a la propiedad y poner un punto de interrupción dentro. El formulario que describo necesita la dirección de memoria, si no tiene forma de saberlo, hay que buscar otros métodos.
momboco
9

Cambie la variable a una propiedad y agregue un punto de interrupción en el método establecido. Ejemplo:

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

    set { 
        m_var = value;
    }
}
Marcello
fuente
3

Si está utilizando WPF, hay una herramienta increíble: WPF Inspector .
Se adjunta a una aplicación WPF y muestra el árbol completo de controles con todas las propiedades, y le permite (entre otras cosas) interrumpir cualquier cambio de propiedad.

Pero lamentablemente no encontré ninguna herramienta que te permitiera hacer lo mismo con CUALQUIER propiedad o variable.

Julien N
fuente
2

Hacer clic derecho en el punto de interrupción funciona bien para mí (aunque sobre todo lo estoy usando para puntos de interrupción condicionales en valores de variables específicas. Incluso romper en expresiones que involucran un nombre de subproceso funciona, lo cual es muy útil si está tratando de detectar problemas de subprocesamiento).

Oskar
fuente
2

Como Peter Mortensen escribió:

En el menú de Visual Studio 2005:

Depuración -> Nuevo punto de interrupción -> Nuevo punto de interrupción de datos

Ingrese: & myVariable

Información Adicional:

Obviamente, el sistema debe saber qué dirección en la memoria mirar. Entonces, establezca un punto de interrupción normal para la inicialización de myVariable(o myClass.m_Variable), ejecute el sistema y espere hasta que se detenga en ese punto de interrupción. - Ahora la entrada del menú está habilitada, y puede ver la variable ingresando &myVariable, o la instancia ingresando &myClass.m_Variable. Ahora las direcciones están bien definidas.

Lo siento cuando hice las cosas mal al explicar una solución ya dada. Pero no pude agregar un comentario, y ha habido algunos comentarios al respecto.

R Risack
fuente
1

Puede usar un punto de observación de memoria en código no administrado. Sin embargo, no estoy seguro de si están disponibles en el código administrado.

1800 INFORMACIÓN
fuente
1

Probablemente pueda hacer un uso inteligente de la función DebugBreak () .

wip
fuente
¿Cómo exactamente? ¿Al ejecutar un hilo separado en un bucle cerrado e invocar DebugBreak () cada vez que se encuentra un cambio?
nalply
@nalpy Podría, por ejemplo, rastrear los lugares donde myVariablese usa y almacenar sus valores después de su uso en una previousValuevariable auxiliar , luego llamar a DebugBreak () cuando myVariable!=previousValue; entonces sabría entre qué bloques de código myVariableha cambiado. Pero estoy de acuerdo en que la solución de AShelly es la mejor.
wip
1

Opcionalmente, puede sobrecargar el operador = para la variable y puede poner el punto de interrupción dentro de la función sobrecargada en una condición específica.

PRINCIPAL
fuente
1

Actualización en 2019:

Esto ahora es oficialmente compatible con Visual Studio 2019 Preview 2 para .Net Core 3.0 o superior. Por supuesto, es posible que tenga que reflexionar sobre los riesgos potenciales de usar una versión de IDE de vista previa. Me imagino que en un futuro próximo esto se incluirá en el Visual Studio oficial.

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

¡Afortunadamente, los puntos de corte de datos ya no son exclusivos de C ++ porque ahora están disponibles para .NET Core (3.0 o superior) en Visual Studio 2019 Preview 2!

Mate
fuente