Editar

Share via


Perguntas frequentes de depuração de código nativo

Como depurar violações de acesso ao executar meu programa fora do depurador do Visual Studio?

Defina a opção depuração Just-In-Time e execute o programa autônomo, até que ocorra a violação de acesso. Em seguida, na caixa de diálogo Violação de Acesso, clique em Cancelar para iniciar o depurador.

Como depurar uma violação de acesso de C++?

Quando você recebe uma violação de acesso em uma linha de código que cancela a referência a diversos ponteiros, pode ser difícil descobrir qual ponteiro causou a violação. No Visual Studio, a caixa de diálogo de exceção nomeia explicitamente o ponteiro que causou a violação de acesso.

Por exemplo, no caso do seguinte código, você terá uma violação de acesso:

#include <iostream>
using namespace std;

class ClassC {
public:
  void printHello() {
    cout << "hello world";
  }
};

class ClassB {
public:
  ClassC* C;
  ClassB() {
    C = new ClassC();
  }
};

class ClassA {
public:
  ClassB* B;
  ClassA() {
    // Uncomment to fix
    // B = new ClassB();
  }
};

int main() {
  ClassA* A = new ClassA();
  A->B->C->printHello();

}

Se você executar esse código no Visual Studio, verá a seguinte caixa de diálogo de exceção:

Screenshot of a Microsoft Visual Studio exception dialog, showing a read access violation for 'A->B was nullptr'. The Break button is selected.

Se não for possível determinar por que o ponteiro causou uma violação de acesso, rastreie o código para certificar-se de que o ponteiro que está causando o problema foi atribuído corretamente. Se ele for transmitido como um parâmetro, verifique se isso foi feito corretamente e se você não está criando acidentalmente uma cópia superficial. Em seguida, verifique se os valores não estão sendo alterados acidentalmente em algum lugar do programa, criando um ponto de interrupção de dados para o ponteiro em questão a fim de garantir que ele não seja modificado em outro lugar do programa. Para saber mais sobre os pontos de interrupção de dados, confira a seção de ponto de interrupção de dados em Usar pontos de interrupção.

Como posso descobrir se meus ponteiros corrompem um endereço de memória?

Verifique se há corrupção de heap. A maioria das corrupções de memória ocorre devido à corrupção de heap. Tente usar o utilitário global dos sinalizadores (gflags.exe) ou pageheap.exe. Confira /windows-hardware/drivers/debugger/gflags-and-pageheap.

Para descobrir onde o endereço de memória foi modificado:

  1. Defina um ponto de interrupção de dados em 0x00408000. Confira Definir um ponto de interrupção de alteração de dados (somente C++ nativo).

  2. Quando você atingir o ponto de interrupção, use a janela Memória para exibir o conteúdo da memória que começa em 0x00408000. Para saber mais, confira Janelas de memória.

Como descobrir quem está transmitindo um valor de parâmetro errado?

Para resolver esse problema:

  1. Defina um local de ponto de interrupção no início da função.

  2. Clique com o botão direito do mouse no ponto de interrupção e selecione Condição.

  3. Na caixa de diálogo Condição de Ponto de Interrupção, clique na caixa de seleção Condição. Confira Pontos de interrupção avançados.

  4. Digite uma expressão, como Var==3, na caixa de texto, onde Var é o nome do parâmetro que contém o valor incorreto, e 3 é o valor incorreto passado para ele.

  5. Selecione o botão de opção é True e clique no botão OK.

  6. Agora, execute o programa novamente. O ponto de interrupção faz com que o programa pare no início da função quando o parâmetro Var tiver o valor 3.

  7. Use a janela Pilha de Chamadas para localizar a função de chamada e navegar até seu código-fonte. Para saber mais, confira Como: usar a janela de pilha de chamadas.

Ao chamar uma função centenas de vezes, como saberei qual chamada falhou?

Exemplo: meu programa falha em uma chamada para uma determinada função, CnvtV. O programa provavelmente chama essa função algumas centenas de vezes antes de falhar. Se eu definir um ponto de interrupção de local em CnvtV, o programa parará em cada chamada a essa função, e eu não quero isso. Eu não sei quais condições causam a falha na chamada, portanto, não consigo definir um ponto de interrupção condicional. O que posso fazer?

Você pode definir um ponto de interrupção na função com o campo Contagem de Ocorrências para um valor mais alto que nunca será atingido. Nesse caso, como você acredita que a função CnvtV será chamada algumas centenas de vezes, defina a Contagem de Ocorrências como 1000 ou mais. Execute o programa e aguarde a chamada falhar. Quando falhar, abra a janela Pontos de Interrupção e verifique a lista de pontos de interrupção. O ponto de interrupção definido em CnvtV aparece, seguido pela contagem de ocorrências e o número de iterações restantes:

CnvtV(int) (no condition) when hit count is equal to 1000 (currently 101)

Agora você sabe que a função falha na 101a chamada. Se você redefinir o ponto de interrupção com uma contagem de ocorrências de 101 e executar o programa novamente, o programa de chamada parará na chamada para CnvtV que causou a falha.

Onde posso pesquisar códigos de erro do Win32?

WINERROR.H no diretório INCLUDE de sua instalação padrão do sistema contém as definições de código de erro para as funções da API do Win32.

Você pode pesquisar um código de erro digitando o código na janela Inspeção ou na caixa de diálogo QuickWatch. Por exemplo:

0x80000004,hr

Como manter o foco ao percorrer o aplicativo?

Exemplo: meu programa tem um problema de ativação de janela. Percorrer o programa com o depurador interfere em minha capacidade de reproduzir o problema, pois meu programa sempre perde o foco. Há alguma maneira de evitar a perda de foco?

Se você tiver um segundo computador, use a depuração remota. Você pode operar seu programa no computador remoto quando executar o depurador no host. Para saber mais, confira Como: selecionar um computador remoto.

Como posso depurar as funções de API do Windows?

Para definir um ponto de interrupção em uma função da API do Windows com símbolos NT carregados, faça o seguinte:

  • No ponto de interrupção da função, insira o nome da função com o nome da DLL em que ela está (confira o operador de contexto). No código de 32 bits, use a forma decorada do nome da função. Para definir um ponto de interrupção em MessageBeep, por exemplo, você precisa inserir o seguinte.

    {,,USER32.DLL}_MessageBeep@4
    

    Para saber o nome decorado, confira Exibir os nomes decorados.

    É possível testar o nome decorado e exibi-lo no código de desmontagem. Enquanto estiver pausado na função no depurador do Visual Studio, clique com o botão direito do mouse nela no editor de código ou chame a janela da pilha e escolha Acessar desmontagem.

  • No código de 64 bits, é possível usar o nome não decorado.

    {,,USER32.DLL}MessageBeep
    

Próximas etapas

Saiba mais sobre a depuração de códigos nativos no Visual Studio por meio destes links: