Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A partir da versão 10.0.25310.1001 do mecanismo de depurador, agora há suporte para a resolução de pontos de interrupção ambíguos.
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 acontecer 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 inserido.
- Definindo um ponto de interrupção em uma função de modelo com várias instanciações na janela de origem.
Quando ativado, o depurador definirá um ponto de interrupção em cada símbolo correspondente para uma certa expressão de ponto de interrupção. O depurador também filtrará correspondências de símbolos se determinados critérios forem atendidos.
Para obter informações gerais sobre como usar pontos de interrupção, consulte Como usar pontos de interrupção.
Habilitando a resolução de pontos de interrupção ambíguos
Por padrão, pontos de interrupção ambíguos são desabilitados. Para habilitar isso em uma sessão de 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 como false. Para garantir que a configuração persista entre as sessões, certifique-se de clicar em File -> Settings -> Debugger Settings e então marcar a caixa Persist engine settings across debugger sessions.
O uso se aplica a pontos de interrupção únicos
Resolver 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 configuração de vários pontos de interrupção com o bm comando continuará funcionando normalmente. Ao executar o comando com esse recurso habilitado, obter-se-á 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, outro ponto de interrupção será criado para controlar o conjunto de pontos de interrupção. Esse ponto de interrupção de sobreposição, o ponto de interrupção hierárquico, pode ser habilitado/desabilitado/desmarcado e listado da mesma forma que 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 com o símbolo bar, um ponto de interrupção hierárquico será criado que controla as duas correspondências. Se o hierárquico estiver habilitado/desabilitado/desmarcado, também serão os pontos de interrupção correspondentes.
Os .bpcmds (Comandos de Ponto de Interrupção de Exibição) listarão o comando de ponto de interrupção que pode ser executado para definir cada ponto de interrupção. 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 no endereço desse ponto de interrupção. 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
Definir um ponto de interrupção em um nome de símbolo deverá 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,bmdeve ser usado para definir pontos de interrupção na função de modelo.Não há suporte para especificações parciais de modelo pelo depurador e nenhum ponto de interrupção será definido nesse caso.
Uma função embutida: cada local embutido 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 exigem mais avaliação pelo depurador. Por exemplo, se o símbolo foo se resolver para vários locais, mas a expressão foo+5 for avaliada, o depurador não tentará resolver todos os locais para definir os pontos de interrupção.
Exemplos de código de ponto de interrupção
Dado o seguinte trecho de código:
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
Definir um ponto de interrupção em uma linha de origem deve resultar no seguinte comportamento se a linha de origem for:
- Uma função com otimização de 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 inline: um ponto de interrupção é definido para cada um dos pontos de chamada, a menos que a linha especificada tenha sido otimizada como parte do inlining.
- 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 endereços N tiver nenhum deslocamento de linha de origem 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 endereços N que tenham nenhum deslocamento de linha de origem 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 SYMBOL_INFO estrutura.
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 na linha de origem.
Exemplos de modelo e funções sobrecarregadas
Funções de modelo
Definir 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 correspondem às implementações da função template que são utilizadas mais adiante 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<int>}
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
Definir 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 snippet 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 de 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
Definir 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 controlarão todos os pontos de interrupção em seu conjunto, a menos que:
Um ponto de interrupção em seu conjunto é removido.
- O ponto de interrupção hierárquico foi removido.
- 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 ter outro ponto de interrupção hierárquico.
Subsumir 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, A será incluída no novo conjunto de pontos de interrupção com B.
Subsumir interseções de conjuntos hierárquicos 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 será resolvida para criar pontos de interrupção:
B, C, D: os pontos de interrupção B, C se juntarão ao novo grupo hierárquico de pontos de interrupção com o ponto de interrupção D, e o ponto de interrupção hierárquico A será removido.
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 ponto de interrupção restante que não se juntou ao novo grupo.
Consulte também
Sintaxe do ponto de interrupção