Partilhar via


Resolução ambígua de ponto de interrupção

Na versão 10.0.25310.1001 e posterior do mecanismo do depurador, agora há suporte para a resolução ambígua de ponto de interrupção.

Pontos de interrupção ambíguos permitem que o depurador defina pontos de interrupção em determinados cenários em que uma expressão de ponto de interrupção é resolvida para vários locais. Por exemplo, isso pode ocorrer quando:

  • Várias sobrecargas de uma função.
  • Há vários símbolos que correspondem a uma expressão de ponto de interrupção.
  • O mesmo nome de símbolo é usado para vários locais.
  • O símbolo foi embutido.
  • Definir um ponto de interrupção em uma função de modelo com várias instanciações na janela de origem.

Quando habilitado, o depurador definirá um ponto de interrupção em cada correspondência de símbolo para uma determinada expressão de ponto de interrupção. O depurador também filtrará as correspondências de símbolo se determinados critérios forem atendidos.

Para obter informações gerais sobre como usar pontos de interrupção, consulte Usando pontos de interrupção.

Habilitando a resolução ambígua de ponto de interrupção

Por padrão, os pontos de interrupção ambíguos são desabilitados. Para habilitar isso em uma sessão do depurador, execute este comando no console do WinDbg:

dx @$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints = true;

Para confirmar se a configuração de pontos de interrupção ambíguos está ativa:

0:010> dx @$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints
@$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints                 : true

Para obter mais informações sobre usar o comando dx, consulte dx (expressão para exibir modelo de objeto de depurador).

Para desabilitar o recurso, defina o valor acima para ser false. Para garantir que a configuração persista entre as sessões, clique em File -> Settings -> Debugger Settings e marque a caixa marcada Persist engine settings across debugger sessions.

O uso se aplica a pontos de interrupção únicos

A resolução de expressões de ponto de interrupção ambíguas só se aplica à execução do comando de ponto de interrupção para definir um único ponto de interrupção no depurador. Em outras palavras, a definição de vários pontos de interrupção com o comando bm continuará funcionando normalmente. A execução do comando com esse recurso habilitado resultará em um novo comportamento de ponto de interrupção para pontos de interrupção únicos.

Para obter informações gerais sobre os comandos de ponto de interrupção, consulte bp, bu, bm (Definir ponto de interrupção).

Pontos de interrupção hierárquicos

Pontos de interrupção hierárquicos representam o resultado da resolução de uma expressão de ponto de interrupção ambígua para vários pontos de interrupção. Se uma expressão resultar em duas ou mais correspondências que serão usadas para definir pontos de interrupção, será criado outro ponto de interrupção que controlará o conjunto de pontos de interrupção. Esse ponto de interrupção de substituição, o ponto de interrupção hierárquico, pode ser habilitado/desabilitado/limpo e listado exatamente como um ponto de interrupção normal, com a funcionalidade adicional de executar a mesma operação nos pontos de interrupção que possui.

Por exemplo, se o comando bp foo!bar for executado, resultando em duas correspondências em relação ao símbolo bar, será criado um ponto de interrupção hierárquico que controla as duas correspondências. Se a hierarquia estiver habilitada/desabilitada/desmarcada, também serão os pontos de interrupção correspondentes.

O .bpcmds (Exibir comandos de ponto de interrupção) listará o comando de ponto de interrupção que pode ser executado para definir cada ponto de interrupção. Os pontos de interrupção que pertencem a um ponto de interrupção hierárquico ainda listarão um comando bp válido que definirá um ponto de interrupção em seu endereço. Os pontos de interrupção hierárquicos também serão listados na saída e exibirão o comando que pode ser usado para recriar todo o conjunto de pontos de interrupção em vez de apenas um único ponto de interrupção.

Símbolos ambíguos

A definição de um ponto de interrupção em um nome de símbolo deve resultar no seguinte comportamento se o símbolo for:

  • Uma sobrecarga: cada sobrecarga que corresponde ao símbolo deve ter um ponto de interrupção.

  • Uma função de modelo:

    • Se a expressão tiver todos os parâmetros de modelo especificados (por exemplo, bp foo!bar<int>), um ponto de interrupção será definido na implementação específica da função de modelo.

    • Se a expressão não tiver nenhuma implementação de tipo especificada (por exemplo bp foo!bar, ), nenhum ponto de interrupção será definido. Nesse caso, bm deve ser usado para definir pontos de interrupção na função de modelo.

    • As especificações parciais do modelo não são suportadas pelo depurador e nenhum ponto de interrupção será definido nesse caso.

  • Uma função embutida: cada local alinhado tem um ponto de interrupção

Observe que vários pontos de interrupção não serão definidos quando a expressão de símbolo incluir operadores ou deslocamentos que exijam mais avaliação pelo depurador. Por exemplo, se o símbolo foo for resolvido para vários locais, mas a expressão foo+5 for avaliada, o depurador não tentará resolver todos os locais para que os pontos de interrupção sejam definidos.

Exemplos de código de ponto de interrupção

Dado o snippet de código a seguir:

class BikeCatalog
{
public:
    void GetNumberOfBikes()
    {
        std::cout << "There are 42 bikes." << std::endl;
    }
    int GetNumberOfBikes(int num)
    {
        std::cout << "There are " << num << " bikes." << std::endl;
        return num;
    }
}; 

Invocar o comando bu BikeCatalog::GetNumberOfBikes resultaria na criação de dois pontos de interrupção, um para cada sobrecarga. Listar os pontos de interrupção resultaria na seguinte saída:

0:000> bl
     2 e Disable Clear  <hierarchical breakpoint>     0001 (0001)  0:**** {BikeCatalog!BikeCatalog::GetNumberOfBikes}
         0 e Disable Clear  00007ff6`c6f52200  [C:\BikeCatalog\BikeCatalog.cpp @ 13]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes
         1 e Disable Clear  00007ff6`c6f522a0  [C:\BikeCatalog\BikeCatalog.cpp @ 9]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes

Linhas de origem ambíguas

A definição de um ponto de interrupção em uma linha de origem deve resultar no seguinte comportamento se a linha de origem for:

  • Uma função otimizada para compilador: Se a linha for dividida em vários locais devido a otimizações do compilador, um ponto de interrupção será definido no local mais baixo dentro da função correspondente à linha especificada.
  • Uma função embutida: um ponto de interrupção é definido para cada um dos sites de chamada, a menos que a linha especificada tenha sido otimizada como parte do embutimento.
  • Resolvido para vários locais: se as condições acima não forem atendidas, um ponto de interrupção será definido para cada endereço com as seguintes condições:
    • Se houver um conjunto de N endereços que correspondam à linha de origem na expressão, e um subconjunto M desses N endereços tiver deslocamento de linha de origem zero da linha de origem na expressão, somente os endereços M terão pontos de interrupção.
    • Se não houver endereços no conjunto de N endereços que tenham deslocamento de linha de origem zero da linha de origem na expressão, todos os endereços N terão pontos de interrupção.

Filtragem com base no índice de símbolos

Cada símbolo deve ter um índice de símbolo exclusivo. Para obter informações detalhadas sobre a estrutura de símbolos, consulte Estrutura SYMBOL_INFO.

O depurador usará o índice de símbolos para garantir que as correspondências duplicadas sejam filtradas no caso de vários endereços com deslocamento zero da linha de origem.

Exemplos de modelos e funções sobrecarregadas

Funções de modelo

A definição de um ponto de interrupção na linha de origem para a definição de uma função de modelo resultará em um ponto de interrupção para cada implementação da função de modelo. Dada a seguinte função de modelo na linha 19 de BikeCatalog.cpp:

template <class T>
void RegisterBike(T id)
{
    std::cout << "Registered bike " << id << std::endl;
}

E seus usos:

catalog.RegisterBike("gravel bike");
catalog.RegisterBike(1234);

Invocar o comando bp `BikeCatalog.cpp:19` definirá dois pontos de interrupção que resolvem as implementações da função de modelo que são usadas posteriormente no arquivo. Se, em vez disso, o usuário quisesse definir um único ponto de interrupção na função, ele teria que definir um ponto de interrupção na linha de origem específica da implementação da função de modelo ou definir um ponto de interrupção no símbolo da função de modelo com as informações de tipo apropriadas (por exemplo, bp BikeCatalog::RegisterBike<int>).

Listar os pontos de interrupção resulta na seguinte saída:

0:000> bl
     2 e Disable Clear  <hierarchical breakpoint>     0001 (0001)  0:**** {BikeCatalog!BikeCatalog::RegisterBike&lt;int&gt;}
         0 e Disable Clear  00007ff7`6b691dd0  [C:\BikeCatalog\BikeCatalog.cpp @ 20]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::RegisterBike<int>
         1 e Disable Clear  00007ff7`6b691e60  [C:\BikeCatalog\BikeCatalog.cpp @ 20]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::RegisterBike<char const *>

Funções sobrecarregadas

A definição de um ponto de interrupção na linha de origem para a definição de uma função sobrecarregada resultará em apenas um ponto de interrupção nessa definição da função sobrecarregada. Reutilizando o trecho de código acima, com a primeira linha começando na linha 5:

class BikeCatalog
{
public:
    void GetNumberOfBikes()
    {
        std::cout << "There are 42 bikes." << std::endl;
    }
    int GetNumberOfBikes(int num)
    {
        std::cout << "There are " << num << " bikes." << std::endl;
        return num;
    }
}; 

Invocar o comando bp `BikeCatalog.cpp:9` definirá um único ponto de interrupção na linha para a void implementação do GetNumberOfBikes. Listar os pontos de interrupção resulta na seguinte saída:

0:000> bl
     0 e Disable Clear  00007ff7`6b691ec0  [C:\BikeCatalog\BikeCatalog.cpp @ 9]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes

funções embutidas

A definição de um ponto de interrupção na linha de origem para o site de chamada de uma função embutida resultará em apenas um ponto de interrupção nesse site de chamada específico, mesmo que haja outro site de chamada presente na mesma função.

Vários pontos de interrupção hierárquicos

Os pontos de interrupção hierárquicos serão proprietários de cada ponto de interrupção em seu conjunto, a menos que:

Um ponto de interrupção em seu conjunto é limpo

  • O ponto de interrupção hierárquico é limpo.
  • Outro ponto de interrupção hierárquico é criado que inclui um ponto de interrupção no conjunto desse ponto de interrupção hierárquico.

Outra maneira de pensar sobre isso é que os pontos de interrupção podem ter apenas um proprietário de ponto de interrupção hierárquico e que o comando de ponto de interrupção mais recente determinará qual deve ser o estado da lista de pontos de interrupção.

Além disso, um ponto de interrupção hierárquico não pode possuir outro ponto de interrupção hierárquico.

Subsumindo pontos de interrupção pré-existentes

Se um ponto de interrupção A existir por conta própria e, em seguida, uma expressão de ponto de interrupção ambígua for resolvida para criar pontos de interrupção A, B, então A será incluído no novo conjunto de pontos de interrupção com B.

Enviando interseções hierárquicas do conjunto de pontos de interrupção

Se um ponto de interrupção hierárquico A possuir pontos de interrupção B, C e, em seguida, uma expressão de ponto de interrupção ambígua for resolvida para criar pontos de interrupção:

  • B, C, D: Os pontos de interrupção B, C se juntarão ao novo grupo de pontos de interrupção hierárquicos com o ponto de interrupção D, e o ponto de interrupção hierárquico A será limpo.

  • C, D ou B, D: Um dos pontos de interrupção se juntará ao novo grupo de pontos de interrupção hierárquico com o ponto de interrupção D, e o ponto de interrupção hierárquico A continuará a existir com o único ponto de interrupção restante que não ingressou no novo grupo.

Confira também

Usando pontos de interrupção

Sintaxe do ponto de interrupção

bp, bu, bm (Definir ponto de interrupção)

Pontos de interrupção não resolvidos (pontos de interrupção bu)