Dectando memory leaks com Valgrind

Olá pessoal,

Qual é o administrador ou programador em Linux (provalmente em outras plataformas também) não sofreu com memory leaks. Ah!!! Memory leaks?!!? É isso ai!! :)

Podemos definir que memory leaks são endereços de memória alocados mas não liberados em uma aplicação, isto é, o programador alocou X bytes de memória mas não desalocou.  Uma das várias utilidades que o Valgrind nos oferece, é com certeza a análise de memory leaks.
Nesse artigo, criamos dois aplicativos escritos em C. Os dois programas irão alocar 10MB de memória, porém só 1 irá desalocar a memória solicitada. Vamos ao código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void){

    int i;
    char *str;

    for (i=0;i<10;i++){
        str = malloc(1048576); /* aloca 1Mebibytes  -->   $ echo "1*(2^20)"| bc = 1048576 */
        if ( str == NULL){
                perror("Erro no malloc\n");
                exit(1);
        }
        strcpy(str,"Alocando e liberando memória - TchelloBlog");
        printf("%s\n", str);
        free(str); /*  libera memória */
    }
    return 0;
}

Nesse primeiro código, podemos visualizar que a função malloc() é chamada e depois a função free() desaloca a memória. Vejamos o que o Valgrind tem a dizer sobre isso:

$> gcc -Wall -o alloc-normal alloc-normal.c
$> valgrind --tool=memcheck ./alloc-normal
==1968== Memcheck, a memory error detector
==1968== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==1968== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==1968== Command: ./alloc-normal
==1968==
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
Alocando e liberando memória - TchelloBlog
==1968==
==1968== HEAP SUMMARY:
==1968==     in use at exit: 0 bytes in 0 blocks
==1968==   total heap usage: 10 allocs, 10 frees, 10,485,760 bytes allocated
==1968==
==1968== All heap blocks were freed -- no leaks are possible
==1968==
==1968== For counts of detected and suppressed errors, rerun with: -v
==1968== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)

Preste atenção na informação exibida pelo Valgrind acima referente as 10 alocações e 10 liberações de memória.
==1968== in use at exit: 0 bytes in 0 blocks
==1968== total heap usage: 10 allocs, 10 frees, 10,485,760 bytes allocated

Vamos agora ao código comilão de memória e a execução do Valgrind:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void){

    int i;
    char *str;

    for (i=0;i<10;i++){
        str = malloc(1048576); /* aloca 1Mebibytes  -->   $ echo "1*(2^20)"| bc = 1048576 */
        if ( str == NULL){
                perror("Erro no malloc\n");
                exit(1);
        }
        strcpy(str,"Com fome de memória  - TchelloBlog");
        printf("%s\n", str);
    }

    return 0;
}
$> gcc -o alloc-leak alloc-leak.c
$> valgrind --tool=memcheck ./alloc-leak
==2085== Memcheck, a memory error detector
==2085== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2085== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==2085== Command: ./alloc-leak
==2085==
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
Com fome de memória - TchelloBlog
==2085==
==2085== HEAP SUMMARY:
==2085==     in use at exit: 10,485,760 bytes in 10 blocks
==2085==   total heap usage: 10 allocs, 0 frees, 10,485,760 bytes allocated
==2085==
==2085== LEAK SUMMARY:
==2085==    definitely lost: 10,485,760 bytes in 10 blocks
==2085==    indirectly lost: 0 bytes in 0 blocks
==2085==      possibly lost: 0 bytes in 0 blocks
==2085==    still reachable: 0 bytes in 0 blocks
==2085==         suppressed: 0 bytes in 0 blocks
==2085== Rerun with --leak-check=full to see details of leaked memory
==2085==
==2085== For counts of detected and suppressed errors, rerun with: -v
==2085== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
$>

Novamente preste atenção na saída do Valgrind confirmando 10 alocações e informando que o programa terminou com 10MB de memória em 10 blocos.
==2085== HEAP SUMMARY:
==2085== in use at exit: 10,485,760 bytes in 10 blocks
==2085== total heap usage: 10 allocs, 0 frees, 10,485,760 bytes allocated
==2085==
==2085== LEAK SUMMARY:
==2085== definitely lost: 10,485,760 bytes in 10 blocks

Okidonki pessoal!!! Agora quando desconfiarem se aquele programa esta causando memory leak, já sabem o que fazer..

Um quebra costela tchê!