Valgrind - Valgrind

Valgrind
Valgrind logo.png
Autor (es) original (is) Julian Seward
Desenvolvedor (s) Equipe de Desenvolvimento Valgrind
Versão estável 3.16.1 (22 de junho de 2020 ; 6 meses atrás ) [±]  ( 2020-06-22 )
Repositório Edite isso no Wikidata
Sistema operacional Linux
macOS
Solaris
Android
Tipo Profiler , depurador de memória
Licença GNU General Public License
Local na rede Internet www .valgrind .org

Valgrind ( / v Æ l ɡ r ɪ n d / ) é uma ferramenta de programação para a depuração de memória , perda de memória de detecção, e de perfis .

Valgrind foi originalmente projetado para ser uma ferramenta de depuração de memória livre para Linux em x86 , mas desde então evoluiu para se tornar uma estrutura genérica para a criação de ferramentas de análise dinâmica, como verificadores e profilers.

O nome Valgrind é uma referência à entrada principal de Valhalla da mitologia nórdica. Durante o desenvolvimento (antes do lançamento), o projeto foi denominado Heimdall ; entretanto, o nome entraria em conflito com um pacote de segurança.

Visão geral

Valgrind é essencialmente uma máquina virtual que usa técnicas de compilação just-in-time (JIT), incluindo recompilação dinâmica . Nada do programa original é executado diretamente no processador host . Em vez disso, Valgrind primeiro traduz o programa em uma forma temporária e mais simples chamada Representação Intermediária (IR), que é uma forma neutra de processador, baseada em SSA . Após a conversão, uma ferramenta (veja abaixo) está livre para fazer quaisquer transformações que desejar no IR, antes que Valgrind traduza o IR de volta para o código de máquina e deixe o processador host executá-lo. Valgrind recompila o código binário para rodar em CPUs host e alvo (ou simuladas) da mesma arquitetura. Ele também inclui um stub GDB para permitir a depuração do programa de destino conforme ele é executado no Valgrind, com "comandos do monitor" que permitem consultar a ferramenta Valgrind para obter várias informações.

Uma quantidade considerável de desempenho é perdida nessas transformações (e geralmente, o código que a ferramenta insere); normalmente, o código é executado com Valgrind e a ferramenta "nenhum" (que não faz nada para o IR) é executada em 20% a 25% da velocidade do programa normal.

Ferramentas

Memcheck

Existem várias ferramentas incluídas no Valgrind (e várias outras externas). A ferramenta padrão (e mais usada) é Memcheck . Memcheck insere código de instrumentação extra em torno de quase todas as instruções, o que mantém o controle da validade (toda memória não alocada começa como inválida ou "indefinida", até que seja inicializada em um estado determinístico, possivelmente de outra memória) e endereçabilidade (seja o endereço de memória em pontos de interrogação para um bloco de memória alocado não liberado), armazenado nos chamados bits V e A, respectivamente. Conforme os dados são movidos ou manipulados, o código de instrumentação rastreia os bits A e V, de forma que eles estejam sempre corretos em um nível de bit único.

Além disso, o Memcheck substitui o alocador de memória C padrão por sua própria implementação, que também inclui protetores de memória em torno de todos os blocos alocados (com os bits A definidos como "inválidos"). Esse recurso permite que o Memcheck detecte erros off-by-one em que um programa lê ou grava fora de um bloco alocado por uma pequena quantidade. Os problemas que o Memcheck pode detectar e alertar incluem o seguinte:

  • Uso de memória não inicializada
  • Leitura / escrita de memória depois de ter sido free 'd
  • Ler / escrever no final de malloc 'd blocos
  • Perda de memória

O preço disso é o desempenho perdido. Os programas executados no Memcheck geralmente são executados de 20 a 30 vezes mais devagar do que fora do Valgrind e usam mais memória (há uma penalidade de memória por alocação). Portanto, poucos desenvolvedores executam seu código no Memcheck (ou qualquer outra ferramenta Valgrind) o tempo todo. Eles normalmente usam essas ferramentas para rastrear algum bug específico ou para verificar se não há bugs latentes (do tipo que o Memcheck pode detectar) no código.

Outras ferramentas

Além do Memcheck, o Valgrind possui várias outras ferramentas:

  • Nenhum , executa o código na máquina virtual sem realizar nenhuma análise e, portanto, tem a menor sobrecarga de CPU e memória possível de todas as ferramentas. Como o próprio valgrind fornece um rastreamento de uma falha de segmentação , a ferramenta none fornece esse rastreamento com sobrecarga mínima.
  • Addrcheck , semelhante ao Memcheck, mas com sobrecarga de CPU e memória muito menor, capturando menos tipos de bugs. Addrcheck foi removido a partir da versão 3.2.0.
  • Massif , um profiler de heap . O massif-visualizer GUI separado visualiza a saída do Massif.
  • Helgrind e DRD , detectam condições de corrida em código multithread
  • Cachegrind , um criador de perfil de cache . A GUI KCacheGrind separada visualiza a saída do Cachegrind.
  • Callgrind , um callgraph analisador de criado por Josef Weidendorfer foi adicionado a Valgrind a partir da versão 3.2.0. KCacheGrind pode visualizar a saída do Callgrind.
  • DHAT , ferramenta de análise dinâmica de heap que analisa quanta memória é alocada e por quanto tempo, bem como padrões de uso de memória.
  • exp-sgcheck (denominado exp-ptrcheck antes da versão 3.7), uma ferramenta experimental para encontrar erros de saturação de pilha e array global que o Memcheck não consegue encontrar. Alguns códigos resultam em falsos positivos com essa ferramenta.
  • exp-bbv , um simulador de desempenho que extrapola o desempenho de um pequeno conjunto de amostras.

Existem também várias ferramentas desenvolvidas externamente disponíveis. Uma dessas ferramentas é ThreadSanitizer, outro detector de condições de corrida .

Plataformas suportadas

A partir da versão 3.4.0, Valgrind suporta Linux em x86 , x86-64 e PowerPC . Suporte para OS X foi adicionado na versão 3.5.0. Suporte para Linux em ARMv7 (usado por exemplo em certos smartphones ) foi adicionado na versão 3.6.0. O suporte para Solaris foi adicionado na versão 3.11.0. Existem portas não oficiais para outras plataformas do tipo UNIX (como FreeBSD , OpenBSD e NetBSD ). A partir da versão 3.7.0, o suporte à plataforma ARM / Android foi adicionado.

Desde a versão 3.9.0 não há suporte para o Linux no MIPS64 pouco e big endian, para MIPS DSP ASE em MIPS32, para s390x instruções Decimal Floating Point, para Power8 ( Poder ISA 2,07 ) instruções, para Intel AVX2 instruções, para Intel transacional sincronização de extensões , RTM e HLE e suporte inicial para Hardware Transactional Memory on POWER.

História e desenvolvimento

Tem o nome da entrada principal de Valhalla na mitologia nórdica .

O autor original de Valgrind é Julian Seward , que em 2006 ganhou o prêmio Google-O'Reilly Open Source por seu trabalho em Valgrind.

Vários outros também fizeram contribuições significativas, incluindo Cerion Armour-Brown, Jeremy Fitzhardinge, Tom Hughes, Nicholas Nethercote, Paul Mackerras, Dirk Mueller, Bart Van Assche, Josef Weidendorfer e Robert Walsh.

Ele é usado por vários projetos baseados em Linux.

Limitações do Memcheck

Além da penalidade de desempenho, uma limitação importante do Memcheck é sua incapacidade de detectar todos os casos de erros de limite no uso de dados estáticos ou alocados na pilha. O código a seguir passará pela ferramenta Memcheck em Valgrind sem incidentes, apesar de conter os erros descritos nos comentários:

  int Static[5];
  
  int func(void)
  {
    int Stack[5];
  
    Static[5] = 0;  /* Error - Static[0] to Static[4] exist, Static[5] is out of bounds */
    Stack [5] = 0;  /* Error - Stack[0] to Stack[4] exist, Stack[5] is out of bounds */
    
    return 0;
  }

A ferramenta experimental valgrind exp-sgcheck foi escrita para resolver esta limitação no Memcheck. Ele detectará erros de saturação da matriz, desde que o primeiro acesso a uma matriz esteja dentro dos limites da matriz. Observe que exp-sgcheck não detectará a saturação de matriz no código acima, uma vez que o primeiro acesso a uma matriz está fora dos limites, mas detectará o erro de saturação de matriz no código a seguir.

  void func(void)
  {
    int i, Stack[5];

    for (i = 0; i <= 5; i++)
        Stack [i] = 0;        /* Within bounds for i=0..4, out of bounds error when i=5 */
  }

A incapacidade de detectar todos os erros envolvendo o acesso aos dados alocados da pilha é especialmente notável, uma vez que certos tipos de erros de pilha tornam o software vulnerável ao exploit clássico de destruição de pilha .

Veja também

Notas

Referências

links externos