Valgrind détecte une fuite de mémoire...

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour tout le monde,

En pleine rédaction de mon tutoriel pour le CdS sur les arbres, je décide de tester ma propre implémentation avec valgrind, histoire d'être sûr que tout soit clean. Et là, c'est le drame :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
==1562== Memcheck, a memory error detector
==1562== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==1562== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==1562== Command: ./main
==1562== Parent PID: 913
==1562== 
==1562== 
==1562== HEAP SUMMARY:
==1562==     in use at exit: 24 bytes in 6 blocks
==1562==   total heap usage: 13 allocs, 7 frees, 112 bytes allocated
==1562== 
==1562== 4 bytes in 1 blocks are definitely lost in loss record 1 of 6
==1562==    at 0x402B41C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1562==    by 0x8048824: bst_add (bst.c:97)
==1562==    by 0x804858E: main (main.c:19)
==1562== 
==1562== 4 bytes in 1 blocks are definitely lost in loss record 2 of 6
==1562==    at 0x402B41C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1562==    by 0x8048824: bst_add (bst.c:97)
==1562==    by 0x80485BB: main (main.c:23)
==1562== 
==1562== 4 bytes in 1 blocks are definitely lost in loss record 3 of 6
==1562==    at 0x402B41C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1562==    by 0x8048824: bst_add (bst.c:97)
==1562==    by 0x80485E8: main (main.c:27)
==1562== 
==1562== 4 bytes in 1 blocks are definitely lost in loss record 4 of 6
==1562==    at 0x402B41C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1562==    by 0x8048824: bst_add (bst.c:97)
==1562==    by 0x8048615: main (main.c:31)
==1562== 
==1562== 4 bytes in 1 blocks are definitely lost in loss record 5 of 6
==1562==    at 0x402B41C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1562==    by 0x8048824: bst_add (bst.c:97)
==1562==    by 0x8048642: main (main.c:35)
==1562== 
==1562== 4 bytes in 1 blocks are definitely lost in loss record 6 of 6
==1562==    at 0x402B41C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==1562==    by 0x8048824: bst_add (bst.c:97)
==1562==    by 0x804866F: main (main.c:39)
==1562== 
==1562== LEAK SUMMARY:
==1562==    definitely lost: 24 bytes in 6 blocks
==1562==    indirectly lost: 0 bytes in 0 blocks
==1562==      possibly lost: 0 bytes in 0 blocks
==1562==    still reachable: 0 bytes in 0 blocks
==1562==         suppressed: 0 bytes in 0 blocks
==1562== 
==1562== For counts of detected and suppressed errors, rerun with: -v
==1562== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)

Allons voir la ligne qui a l'air de provoquer le souci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void bst_add(bst* tree, void* element) {
    // Creating the new node
    bst_node* node = malloc(sizeof(bst_node));
    node->data = malloc(tree->data_size); // ICI
    memcpy(node->data, element, tree->data_size);
    node->left = NULL;
    node->right = NULL;

    if(tree->root)
        bst_add_rec(tree, tree->root, node);
    else {
        tree->root = node;
    }
}

Je sauvegarde bien le pointeur renvoyé par malloc quelque part, alors en quoi y a-t-il fuite de mémoire ?

P.S. : Je sais assurément que tree->data_size est cohérent et je libère tout bien comme il faut un peu plus loin dans le code.

Lu'!

  • Toujours contrôler le retour de malloc.
  • un petit assert sur "tree" en entrée ne serait pas de trop.

Ce serait pas mal de voir le code appelant et idéalement bst_add_rec et le code de libération.

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+1 -0
Auteur du sujet

Tout est !

Et voici le code appelant. (J'ai repris les lignes où valgrind râle)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdlib.h>
#include <stdio.h>
#include "bst.h" // Don't forget that bit

int comp(void* a, void* b) {
    return *((int*) a) - *((int*) b); // (a-b)>0 if a>b, <0 otherwise
}

void print(void* a) {
    printf("%d\t", *((int*) a));
}

int main(int argc, char* argv[]) {
    bst* tree;
    int values = 10;

    printf("Creating tree...\n");
    tree = bst_new(sizeof(int), comp, NULL);
    printf("Done.\n");

    printf("Adding %d...\n", value);
    bst_add(tree, &value); // ICI

    value = 5;  
    printf("Adding %d...\n", value);
    bst_add(tree, &value); / ICI

    value = 12;
    printf("Adding %d...\n", value);
    bst_add(tree, &value); // ICI

    value = 15;
    printf("Adding %d...\n", value);
    bst_add(tree, &value); // ICI

    value = 17;
    printf("Adding %d...\n", value);
    bst_add(tree, &value); // ICI

    value = 13;
    printf("Adding %d...\n", value);
    bst_add(tree, &value); // ICI

    printf("Printing data...\n");
    bst_iter(tree, print);
    printf("Done.\n");

    printf("Destroying tree...\n");
    bst_destroy(tree);
    printf("Done.\n");

    return EXIT_SUCCESS;
}

Édité par Richou D. Degenne

L'allocation est faite ici, où est faite la désallocation ? Quand est-ce que l'arbre est supprimé ?

Si tu ne supprimes pas l'arbre avant de quitter le programme, les points relevés ci-dessus sont normaux. Faire confiance à l'OS pour libérer la mémoire, ce n'est pas une erreur en soit, Valgrind signale juste qu'il reste de la mémoire allouée à la fin de l'exécution, au cas où ce ne serait pas le comportement attendu.

PS: bon, visiblement, tu appelles bst_destroy. On peut avoir son code source ?

+0 -0

Cette réponse a aidé l'auteur du sujet

1
bst_new(&tree, sizeof(int), comp, NULL);
1
2
3
4
5
bst* bst_new(size_t data_size, orderFun compare, freeFun free) {
//...
    tree->free = free;
//...
}
1
2
3
4
5
6
static void bst_destroy_rec(bst* tree, bst_node* current) {
//...
    if(tree->free)
        tree->free(current->data);
//...
}

Tu n'as pas donné de libérateur pour les datas.

Édité par Ksass`Peuk

First : Always RTFM - "Tout devrait être rendu aussi simple que possible, mais pas plus." A.Einstein

+1 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte