Introducao-ao-valgrind

Você vai aprender

  • O que é o Valgrind.

  • Como utilizar essa ferramenta para visualizar manejamento de memória.

  • O que a ferramenta não é capaz de fazer.

Pré-requisitos

Conhecendo a ferramenta

Valgrind é uma ferramenta de depuração e perfilamento de programas de Linux (infelizmente não tem como usá-lo no Windows). Sua função é detectar problemas de uso de memória e é perfeito para o programador de C que está usando funções como malloc e o free.

Ele pode ser usado para encontrar erros de uso de memória igual o GDB, porém sua função mais útil é encontrar vazamentos de memória.

Verificando vazamentos de memória

Primeiramente, instale o valgrind na sua máquina. Você consegue instalar ele utilizando a maioria dos gerenciadores de pacotes do linux como o apt das distros Debian (Ubuntu, Mint, PopOs) ou o pacman das distros Arch (Arch, Manjaro, Garuda).

Com o programa instalado, podemos testar o seu uso.

Considere o programa abaixo:

Como pode ver, este é um programa simples onde declaramos uma String, e fazemos a leitura pelo teclado usando a função getline.

Inclusive se você rodar esse programa, perceberá que não tem nada de errado na mesma.

Entretanto, se olharmos mais de perto, percebe-se que não colocamos a função free, que irá liberar o ponteiro dessa String da memória gerando um vazamento. Podemos verificar isso utilizando o Valgrind, para isso precisamos primeiro usar a diretiva '-g' igual vimos na aula de GDB.

Ótimo, agora iremos rodar o Valgrind, passando a execução do nosso programa como parâmetro.

Se digitarmos uma String qualquer o programa irá finalizar e o Valgrind irá imprimir na tela um registro com o uso de memória do programa.

Percebe que, apesar de nenhum erro ser encontrado, ele detectou que houve uso da heap que não foi liberado, resultando em perca de memória da mesma. Para maior detalhes, o Valgrind nos dá o conselho de adicionar a diretiva

Para visualizar em maior detalhe onde está acontecendo o erro, logo iremos rodar novamente o programa, dessa vez usando

Pílula

Você também consegue colocar os resultados do valgrind em um arquivo separado, usando a diretiva

--log-file="nome-do-arquivo.log"

Rodando novamente o comando, conseguimos o seguinte resultado:

Percebe-se duas coisas: primeiro que um erro foi efetivamente detectado, e segundo, o valgrind nos mostrou exatamente onde aconteceu o problema.

Percebe que a função getline faz alocação dinâmica da String usando malloc, o que justifica porque o nosso programa gerou esse erro, que pode ser resolvido se utilizarmos a função free antes da função main acabar.

Agora que o free foi colocado, nenhum erro será encontrado.

Checagem de erros

Como dito anteriormente, podemos utilizar o Valgrind para checar também uso incorreto de memória. Considere o código abaixo.

Considere a variável "vetor" como sendo um array de inteiros de tamanho cinco. Logo após isso, tentamos inserir no index seis, algo que deveria ser impossível, mas que a linguagem permite.

Se tentarmos rodar esse código junto ao Valgrind, recebemos a seguinte mensagem de erro.

Nenhuma falha de segmentação ocorre, mas o programa alerta sobre uma tentativa de escrita inválida na variável, além de claro, o fato que não liberamos a memória com a função free.

Outro possível erro que pode acontecer é quando o programador faz uma operação em um vetor que está parcialmente inicializado.

Considere o código abaixo.

Neste código estamos criando uma String por alocação dinâmica e depois imprimindo o tamanho da mesma, usando a função strlen. Este código se rodarmos normalmente não irá mostrar nenhum erro, porém o Valgrind irá nos alertar de um problema.

Perceba que a nossa String foi inicializada usando o malloc. Voltando para a nossa aula de iniciação a ponteiros, a função malloc irá iniciar os seus vetores com lixo de memória. Então, apesar do processo de alocação ter sido um sucesso, o nosso vetor ainda está com erro, pois a função strlen está tentando ler uma String que contém apenas lixo.

Para consertar esse problema podemos usar a função memset para preencher o vetor com algum valor de nossa escolha, ou usar a função calloc para iniciar o vetor e já inicializar as posições com o espaço em branco.

Se rodarmos esse código pelo Valgrind, percebe-se que nenhum erro pode ser encontrado.

Veja mais tutoriais do Valgrind

Tutorial mais avançado de Valgrind

Site oficial do Valgrind

Last updated