180 votes

Fuite toujours atteignable détectée par Valgrind

Toutes les fonctions mentionnées dans ce bloc sont des fonctions de bibliothèque. Comment puis-je rectifier cette fuite de mémoire ?

Il est répertorié sous la rubrique " Toujours joignable catégorie ". (Il y en a 4 autres, qui sont très similaires, mais de tailles différentes)

 630 bytes in 1 blocks are still reachable in loss record 5 of 5
    at 0x4004F1B: calloc (vg_replace_malloc.c:418)
    by 0x931CD2: _dl_new_object (dl-object.c:52)
    by 0x92DD36: _dl_map_object_from_fd (dl-load.c:972)
    by 0x92EFB6: _dl_map_object (dl-load.c:2251)
    by 0x939F1B: dl_open_worker (dl-open.c:255)
    by 0x935965: _dl_catch_error (dl-error.c:178)
    by 0x9399C5: _dl_open (dl-open.c:584)
    by 0xA64E31: do_dlopen (dl-libc.c:86)
    by 0x935965: _dl_catch_error (dl-error.c:178)
    by 0xA64FF4: __libc_dlopen_mode (dl-libc.c:47)
    by 0xAE6086: pthread_cancel_init (unwind-forcedunwind.c:53)
    by 0xAE61FC: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126)

Attrapez : Une fois que j'ai exécuté mon programme, il n'a donné aucune fuite de mémoire, mais il avait une ligne supplémentaire dans la sortie de Valgrind, qui n'était pas présente avant :

Rejet des symmes à 0x5296fa0-0x52af438 in /lib/libgcc_s-4.4.4-20100630.so.1 à cause de munmap()

Si la fuite ne peut pas être corrigée, quelqu'un peut-il au moins expliquer pourquoi la ligne munmap() fait que Valgrind rapporte 0 fuite "encore accessible" ?

Editar:

Voici un échantillon de test minimal :

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

void *runner(void *param) {
    /* some operations ... */
    pthread_exit(NULL);
}

int n;

int main(void) {

    int i;
    pthread_t *threadIdArray;

    n=10; /* for example */

    threadIdArray = malloc((n+n-1)*sizeof(pthread_t));  

    for(i=0;i<(n+n-1);i++) {
        if( pthread_create(&threadIdArray[i],NULL,runner,NULL) != 0 ) {
            printf("Couldn't create thread %d\n",i);
            exit(1);
        }
    }

    for(i=0;i<(n+n-1);i++) {
        pthread_join(threadIdArray[i],NULL);
    }

    free(threadIdArray);

    return(0);
}

Fonctionne avec :

valgrind -v --leak-check=full --show-reachable=yes ./a.out

464voto

Dan Moulding Points 46866

Il y a plus d'une façon de définir une "fuite de mémoire". En particulier, il existe deux définitions principales de la "fuite de mémoire" qui sont couramment utilisées par les programmeurs.

La première définition couramment utilisée de la "fuite de mémoire" est la suivante : "De la mémoire a été allouée et n'a pas été ensuite libérée avant la fin du programme." Cependant, de nombreux programmeurs affirment (à juste titre) que certains types de fuites de mémoire qui correspondent à cette définition ne posent en fait aucun problème et ne doivent donc pas être considérés comme des fuites de mémoire. vrai "fuites de mémoire".

Une définition plus stricte (et plus utile) de la "fuite de mémoire" est la suivante : "De la mémoire a été allouée et ". ne peut pas être libérée ultérieurement car le programme n'a plus de pointeurs vers le bloc de mémoire alloué". En d'autres termes, vous ne pouvez pas libérer une mémoire sur laquelle vous n'avez plus de pointeurs. Une telle mémoire est donc une "fuite de mémoire". Valgrind utilise cette définition plus stricte du terme "fuite de mémoire". Il s'agit du type de fuite qui peut potentiellement provoquer un épuisement important du tas, en particulier pour les processus à longue durée de vie.

La catégorie "toujours accessible" dans le rapport de fuite de Valgrind fait référence aux allocations qui correspondent uniquement à la première définition de "fuite de mémoire". Ces blocs n'ont pas été libérés, mais ils auraient pu l'être (si le programmeur l'avait voulu) car le programme gardait toujours la trace des pointeurs vers ces blocs de mémoire.

En général, il n'y a pas lieu de s'inquiéter des blocs "encore accessibles". Ils ne posent pas le type de problème que les vrai Les fuites de mémoire peuvent causer des problèmes. Par exemple, il n'y a normalement aucun risque d'épuisement du tas à partir de blocs "encore accessibles". En effet, ces blocs sont généralement des allocations uniques, dont les références sont conservées pendant toute la durée de vie du processus. Bien que vous puissiez vous assurer que votre programme libère les blocs tous de la mémoire allouée, il n'y a généralement aucun avantage pratique à le faire puisque le système d'exploitation récupérera de toute façon toute la mémoire du processus après que celui-ci se soit terminé. Comparez ceci avec vrai des fuites de mémoire qui, si elles ne sont pas corrigées, peuvent entraîner l'épuisement de la mémoire d'un processus s'il est laissé en marche assez longtemps, ou simplement faire en sorte qu'un processus consomme beaucoup plus de mémoire que nécessaire.

La seule fois où il est utile de s'assurer que toutes les allocations ont des "frees" correspondants est probablement si vos outils de détection de fuites ne peuvent pas dire quels blocs sont "encore accessibles" (mais Valgrind peut le faire) ou si votre système d'exploitation ne récupère pas toute la mémoire d'un processus qui se termine (toutes les plateformes pour lesquelles Valgrind a été porté le font).

11voto

Jens Gustedt Points 40410

Puisqu'il y a une routine de la famille pthread en bas (mais je ne connais pas cette routine en particulier), je pense que vous avez lancé un thread comme joinable qui a terminé son exécution.

L'information sur l'état de sortie de ce thread reste disponible jusqu'à ce que vous appeliez pthread_join . Ainsi, la mémoire est conservée dans un enregistrement de perte à la fin du programme, mais elle est toujours accessible puisque vous pourriez utiliser pthread_join pour y accéder.

Si cette analyse est correcte, lancez ces threads de façon détachée, ou rejoignez-les avant de terminer votre programme.

Modifier : J'ai exécuté votre programme d'exemple (après quelques corrections évidentes) et je n'ai pas d'erreurs mais la suivante.

==18933== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
--18933-- 
--18933-- used_suppression:      2 dl-hack3-cond-1
--18933-- used_suppression:      2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a

Desde el dl- Cette chose ressemble beaucoup à ce que vous voyez, je suppose que vous voyez un problème connu qui a une solution en termes de fichier de suppression pour valgrind . Peut-être que votre système n'est pas à jour, ou que votre distribution ne maintient pas ces choses. (Le mien est ubuntu 10.4, 64bit)

6voto

Abbey Road Points 81

Voici une explication correcte de "toujours joignable" :

"Still reachable" sont des fuites attribuées à des variables globales et statiques-locales. Parce que valgrind suit les variables globales et statiques, il peut exclure les allocations de mémoire qui sont assignées "once-and-forget". Une variable globale à laquelle on a attribué une allocation une fois et qui n'est jamais réattribuée n'est généralement pas une "fuite" dans le sens où elle ne croît pas indéfiniment. Il s'agit toujours d'une fuite au sens strict, mais elle peut généralement être ignorée, sauf si vous êtes pédant.

Les variables locales qui se voient attribuer des allocations et qui ne sont pas libérées sont presque toujours des fuites.

Voici un exemple

int foo(void)
{
    static char *working_buf = NULL;
    char *temp_buf;
    if (!working_buf) {
         working_buf = (char *) malloc(16 * 1024);
    }
    temp_buf = (char *) malloc(5 * 1024);

    ....
    ....
    ....

}

Valgrind rapportera working_buf comme "toujours accessible - 16k" et temp_buf comme "définitivement perdu - 5k".

2voto

Employed Russian Points 50479

Vous ne semblez pas comprendre ce que still reachable signifie.

Tout ce qui est still reachable es pas une fuite. Vous n'avez pas besoin de faire quoi que ce soit.

2voto

MonerosKin Points 31

Pour les futurs lecteurs, "Toujours joignable" peut signifier que vous avez oublié de fermer quelque chose comme un fichier. Bien que cela ne semble pas être le cas dans la question originale, vous devriez toujours vous assurer que vous l'avez fait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X