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

Le problème exposé dans ce sujet a été résolu.

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.

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;
}

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 ?

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.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

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