No Chrome 92, introduzimos o Inspetor de memória, uma ferramenta para inspecionar buffers de memória linear. Neste artigo, vamos falar sobre como melhoramos o Inspector para depuração de C/C++ e os desafios técnicos encontrados ao longo do caminho.
Estas são algumas postagens de blog relevantes se você não conhece a depuração de C/C++ e o Memory Inspector (link em inglês):
- Interessado na depuração de memória profunda? Consulte Introdução ao Inspetor de memória.
- Quer uma introdução ao pacote completo de ferramentas de depuração de C/C++? Consulte Depuração do WASM com ferramentas modernas e Depuração mais rápida do WebAssembly.
Introdução
O Inspetor de memória oferece opções de depuração mais eficientes para buffers de memória linear. No caso de C/C++, você pode inspecionar objetos de memória C/C++ na memória do WebAssembly.
Reconhecer os bytes do seu objeto entre a memória do WebAssembly ao redor era um ponto problemático. Você precisa saber o tamanho do objeto e contar os bytes desde o início. Na captura de tela abaixo, o primeiro byte de uma matriz int32
de 10 elementos está selecionado, mas não está imediatamente claro quais outros bytes pertencem à matriz. Não seria ótimo se você pudesse reconhecer instantaneamente todos os bytes que pertencem ao objeto?
Destaque de objeto no Inspetor de memória
A partir do Chrome 107, o Inspetor de memória destaca todos os bytes de um objeto de memória C/C++. Isso ajuda a diferenciá-los da memória ao redor.
Assista ao vídeo abaixo para ver o Memory Inspector em ação. À medida que você revela a matriz x
no Inspetor de memória, a memória destacada é exibida no Visualizador de memória, junto com um novo ícone logo acima dela. Esse ícone lembra o nome e o tipo da memória destacada. Clique no ícone para acessar a memória do objeto. Se você passar o cursor sobre o ícone, um ícone de cruz vai aparecer. Clique nele para remover o destaque.
Quando você seleciona um byte fora do objeto inspecionado, o destaque desfoca para evitar distrair você. Para mudar o foco novamente, clique novamente em qualquer um dos bytes do objeto ou no ícone.
O suporte ao destaque de objetos não se limita a matrizes. Você também pode inspecionar structs, objetos e ponteiros. Essas mudanças facilitam ainda mais a exploração da memória dos seus apps C/C++.
Quer testar? Será necessário:
- Ter o Chrome 107 ou mais recente.
- Instale a extensão DWARF do C/C++.
- Ative a depuração DWARF no DevTools > Configurações > Experimentos > Depuração WebAssemble: ativar o suporte a DWARF.
- Abra esta página de demonstração.
- Siga as instruções na página.
Exemplo de depuração
Nesta seção, vamos dar uma olhada em um bug para ilustrar como você pode usar o Memory Inspector para depuração de C/C++. No exemplo de código abaixo, um programador cria uma matriz de números inteiros e decide usar a aritmética de ponteiro para selecionar o último elemento. Infelizmente, o programador cometeu um erro no cálculo do ponteiro e agora, em vez de exibir o último elemento, o programa exibe valores sem sentido.
#include <iostream>
int main()
{
int numbers[] = {1, 2, 3, 4};
int *ptr = numbers;
int arraySize = sizeof(numbers)/sizeof(int);
int* lastNumber = ptr + arraySize; // Can you notice the bug here?
std::cout <<../ *lastNumber <<../ '\n';
return 0;
}
O programador recorre ao Inspetor de memória para depurar o problema. Acompanhe esta demonstração. Primeiro, eles inspecionam a matriz no Inspetor de memória e percebem que a matriz numbers
contém apenas os números inteiros 1
, 2
, 3
e 4
, conforme esperado.
Em seguida, ela revela a variável lastNumber
do painel Scope e percebe que o ponteiro aponta para um número inteiro fora da matriz. Com esse conhecimento, o programador percebe que houve um erro na contagem do deslocamento do ponteiro na linha 8. Deve ter sido ptr + arraySize - 1
.
Embora esse seja um exemplo de brinquedo, ele ilustra como o destaque de objeto transmite efetivamente o tamanho e a posição dos objetos de memória, o que pode ajudar você a entender melhor o que está acontecendo na memória do seu aplicativo C/C++.
Como o DevTools descobre o que destacar
Nesta seção, analisaremos o ecossistema de ferramentas que permitem a depuração de C/C++. Especificamente, você aprenderá como DevTools, V8, a extensão DWARF C/C++ e o Emscripten viabilizam a depuração C/C++ no Chrome.
Para aproveitar toda a capacidade da depuração de C/C++ no DevTools, você precisa de duas coisas:
- A extensão C/C++ DWARF instalada no Chrome
- Arquivos de origem C/C++ compilados para o WebAssembly com o compilador Emscripten mais recente, conforme instruído nesta postagem do blog (link em inglês).
Mas por quê? O V8 , o mecanismo JavaScript e WebAssembly do Chrome, não sabe como executar C ou C++. Graças ao Emscripten, um compilador C/C++ para WebAssembly, você pode compilar apps criados em C ou C++ como WebAssembly e executá-los no navegador.
Durante a compilação, o emscripten incorporará dados de depuração do DWARF ao binário. De modo geral, esses dados ajudam a extensão a descobrir quais variáveis do WebAssembly correspondem às suas variáveis C/C++ e muito mais. Dessa forma, o DevTools pode mostrar as variáveis C++ mesmo que o V8 realmente execute o WebAssembly. Se quiser saber mais, confira esta postagem do blog (em inglês) para ver um exemplo de dados de depuração do DWARF.
O que acontece quando você revela o lastNumber
? Assim que você clica no ícone de memória, o DevTools verifica qual variável você quer inspecionar. Em seguida, ela consulta a extensão sobre o tipo de dados e o local de lastNumber
. Assim que a extensão responder com essa informação, o Memory Inspector poderá exibir a fração relevante de memória e saber o tipo dela, também poderá mostrar o tamanho do objeto.
Se você analisar o lastNumber
no exemplo anterior, vai notar que inspecionamos o lastNumber: int *
, mas o que aparece no chip no Memory Inspector (link em inglês)?*lastNumber: int
O inspetor usa a desreferenciamento de ponteiro no estilo C++ para indicar o tipo de objeto mostrado a você. Se você inspecionar um ponteiro, o inspetor mostrará para que ele aponta.
Como manter destaques em etapas do depurador
Quando você revela um objeto no Memory Inspector e usa o depurador, o Inspector mantém o destaque se achar que ainda é aplicável. Inicialmente, não tínhamos esse recurso em nosso roteiro, mas logo percebemos que isso compromete sua experiência de depuração. Imagine ter que inspecionar a matriz novamente após cada etapa, como no vídeo abaixo.
Quando o depurador atinge um novo ponto de interrupção, o Memory Inspector consulta novamente o V8 e a extensão da variável associada ao destaque anterior. Em seguida, ele compara os locais e tipos dos objetos. Se forem iguais, o destaque persiste. No vídeo acima, há uma repetição "for" na matriz x
. Essas operações não mudam o tipo ou a posição da matriz, portanto, ela permanece destacada.
Você deve estar se perguntando como isso afeta os ponteiros. Se você tiver um ponteiro destacado e reatribuí-lo a outro objeto, as posições antiga e nova dos objetos destacados serão diferentes, e o destaque desaparecerá. Como o objeto recém-apontado pode residir em qualquer lugar na memória WebAssembly e provavelmente terá pouca relação com o local da memória anterior, remover o destaque é mais claro do que pular para um novo local da memória. Você pode destacar o ponteiro novamente clicando no ícone de memória dele no painel Scope.
Conclusão
Este artigo descreve nossas melhorias no Inspetor de memória para depuração de C/C++. Esperamos que os novos recursos simplifiquem a depuração da memória dos seus apps C/C++. Se você tiver sugestões para melhorar ainda mais, registre um bug.
O que vem em seguida?
Para saber mais, veja: