Quebrar quando um valor for alterado usando o depurador do Visual Studio


198

Existe uma maneira de colocar um relógio na variável e apenas o Visual Studio quebrar quando esse valor muda?

Seria muito mais fácil encontrar problemas estatais complicados.

Isso pode ser feito?

As condições do ponto de interrupção ainda precisam de um conjunto de pontos de interrupção, e eu prefiro definir um relógio e deixar o Visual Studio definir os pontos de interrupção nas alterações de estado.


mas o ponto de interrupção não afeta nada, a menos que a condição seja mantida, para que você possa colocar seu ponto de interrupção em qualquer lugar (como o Setter) e levá-lo a partir daí. Ou eu estou esquecendo de alguma coisa?
Oskar

6
bem. é como a maneira vb6 de depuração. você não se importa com o local do ponto de interrupção. basta adicionar uma expressão condicional para a janela relógio e VB6 vai gurantee ele vai quebrar sempre que a condição for cumprida ..
Gulzar Nazim

desculpe, nunca vi uma maneira, tanto quanto eu sei o setter é o caminho a percorrer
Oskar

1
eu esperava encontrar melhores notícias; o vs2010 indica nenhuma alteração msdn.microsoft.com/en-us/library/350dyxd0.aspx somente o c ++ nativo possui esse @Scottgu, você pode fazer melhor!
usar o seguinte código

Respostas:


134

No menu do Visual Studio 2005:

Depurar -> Novo ponto de interrupção -> Novo ponto de interrupção de dados

Entrar:

&myVariable

38
isso está disponível para código gerenciado? Vejo essa opção desativada para o projeto C #. Lembre-se de ler em algum lugar que esse é um recurso difícil de implementar na depuração de aplicativos gerenciados, especialmente com o coletor de lixo envolvido.
Gulzar Nazim

27
É só está disponível para código não gerenciado, infelizmente: msdn.microsoft.com/en-us/library/350dyxd0.aspx
Josh Kodroff

17
Você também pode converter temporariamente um campo em uma propriedade e colocar um ponto de interrupção no getter ou setter.
Jon Davis

12
A opção "Ponto de interrupção de dados" em "Depuração -> Novo ponto de interrupção" está desativada. Alguma idéia do porquê? Ele permanece desativado, esteja ou não na verdade, depurando. Estou usando o Visual Studio 2015.
jbb 8/11/16

2
Um pouco atrasado, mas o @jbb para mim só é ativado quando estou parado em um ponto de interrupção durante a depuração.
Allball103

27

Você também pode optar por quebrar explicitamente o código:

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

Do MSDN:

Debugger.Break: se nenhum depurador estiver conectado, os usuários serão perguntados se desejam anexar um depurador. Se sim, o depurador é iniciado. Se um depurador estiver conectado, o depurador será sinalizado com um evento de ponto de interrupção do usuário e o depurador suspenderá a execução do processo como se um ponto de interrupção do depurador tivesse sido atingido.

Esta é apenas uma alternativa, no entanto. Definir um ponto de interrupção condicional no Visual Studio, conforme descrito em outros comentários, é uma escolha melhor.


2
FWIW, com editar e continuar Eu prefiro fazê-lo desta maneira: IME, pontos de interrupção condicionais são sloooow
Mark Sowul

Isso funciona - mas é muito doloroso - acabei fazendo algo semelhante - coloquei isso no topo de todos os métodos que suspeitava - e novamente no final (em uma cláusula finalmente) - dessa maneira eu sabia exatamente qual O método estava causando o problema - (ou seja, eu sabia que os dados eram bons antes de entrar no método e depois ruins antes de sair).
precisa saber é o seguinte

26

Realmente antigo post, mas no caso de alguém não sabe ...

No Visual Studio 2015 , você pode colocar um ponto de interrupção no setacessador de uma propriedade implementada automaticamente e o depurador será interrompido quando a propriedade for atualizada

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

Atualizar

Alternativamente; O @AbdulRaufMujahid indicou nos comentários que, se a propriedade implementada automaticamente estiver em uma única linha, você poderá posicionar o cursor na tecla get;or set;e hit F9e um ponto de interrupção será colocado de acordo. Agradável!

public bool IsUpdated { get; set; }

5
Mesmo que a propriedade implementada automaticamente esteja em uma linha, por exemplo, a sequência pública UserName {set; obter; } O usuário pode destacar getter ou setter e pode pressionar F9 para adicionar ponto de interrupção
Abdul Rauf

@AbdulRaufMujahid Awesome!
Craig

13

Imagine que você tem uma classe chamada A com a seguinte declaração.

class A  
{  
    public:  
        A();

    private:
        int m_value;
};

Você deseja que o programa pare quando alguém modificar o valor de "m_value".

Vá para a definição de classe e coloque um ponto de interrupção no construtor de A.

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

Depois que paramos o programa:

Depurar -> Novo ponto de interrupção -> Novo ponto de interrupção de dados ...

Endereço: & (this-> m_value)
Contagem de bytes: 4 (porque int possui 4 bytes)

Agora, podemos retomar o programa. O depurador irá parar quando o valor for alterado.

Você pode fazer o mesmo com classes herdadas ou classes compostas.

class B
{
   private:
       A m_a;
};

Endereço: & (this-> m_a.m_value)

Se você não souber o número de bytes da variável que deseja inspecionar, poderá usar o operador sizeof.

Por exemplo:

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

Se você olhar para a "Pilha de chamadas", poderá ver a função que alterou o valor da variável.


1
Então, o que exatamente você faria se a coisa que eu estou procurando não estiver nas minhas próprias aulas? Por exemplo, estou tentando descobrir exatamente onde um controle é ativado ou desativado? Posso adicionar um relógio no valor Habilitado do controle durante a depuração, claro, mas não há como fazê-lo interromper as alterações e depois procurar onde parou.
Nyerguds

2
Se você tentar depurar uma biblioteca externa, precisará da biblioteca compilada no modo de depuração. Não estou familiarizado com o componente, mas talvez você possa conectar um "retorno de chamada" à propriedade e colocar um ponto de interrupção dentro. O formulário que eu descrevo precisa do endereço de memória; se você não tem como saber, existe para procurar outros métodos.
Momboco 15/03

9

Mude a variável para uma propriedade e adicione um ponto de interrupção no método set. Exemplo:

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

    set { 
        m_var = value;
    }
}

3

Se você estiver usando o WPF, há uma ferramenta incrível: WPF Inspector .
Ele se conecta a um aplicativo WPF e exibe toda a árvore de controles com todas as propriedades, além de permitir que você (entre outras coisas) interrompa qualquer alteração de propriedade.

Mas, infelizmente, não encontrei nenhuma ferramenta que permitisse fazer o mesmo com QUALQUER propriedade ou variável.



2

Clicar com o botão direito do mouse no ponto de interrupção funciona bem para mim (embora na maioria das vezes eu o esteja usando para pontos de interrupção condicionais em valores de variáveis ​​específicos. Mesmo interromper expressões que envolvam um nome de thread funciona muito útil se você estiver tentando detectar problemas de encadeamento).


2

Como Peter Mortensen escreveu:

No menu do Visual Studio 2005:

Depurar -> Novo ponto de interrupção -> Novo ponto de interrupção de dados

Digite: & myVariable

Informação adicional:

Obviamente, o sistema deve saber qual endereço na memória assistir. Então - defina um ponto de interrupção normal para a inicialização de myVariable(ou myClass.m_Variable) - execute o sistema e aguarde até que ele pare nesse ponto de interrupção. - Agora a entrada Menu está ativada e você pode assistir a variável digitando &myVariableou a instância digitando &myClass.m_Variable. Agora os endereços estão bem definidos.

Desculpe quando fiz as coisas erradas, explicando uma solução já fornecida. Mas não pude adicionar um comentário, e houve alguns comentários sobre isso.


1

Você pode usar um ponto de controle de memória em código não gerenciado. Não tenho certeza se eles estão disponíveis no código gerenciado.


1

Você provavelmente pode fazer um uso inteligente da função DebugBreak () .


Como exatamente? Executando um thread separado em um loop restrito e invocando DebugBreak () sempre que uma alteração for encontrada?
nalply

@nalpy Você pode, por exemplo, rastrear os locais onde myVariableé usado e armazenar seus valores após o uso em uma previousValuevariável auxiliar , e chamar DebugBreak () when myVariable!=previousValue; então você saberia entre quais blocos de código myVariableforam alterados. Mas concordo que a solução da AShelly é a melhor.
wip

1

Opcionalmente, você pode sobrecarregar o operador = para a variável e colocar o ponto de interrupção dentro da função sobrecarregada em uma condição específica.


1

Atualização em 2019:

Agora isso é oficialmente suportado no Visual Studio 2019 Preview 2 para .Net Core 3.0 ou superior. Obviamente, você pode ter que pensar em possíveis riscos ao usar uma versão Preview do IDE. Eu imagino que em um futuro próximo isso será incluído no 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/

Felizmente, os pontos de interrupção de dados não são mais exclusivos do C ++, porque agora estão disponíveis para o .NET Core (3.0 ou superior) no Visual Studio 2019 Preview 2!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.