web-dev-qa-db-fra.com

Fuite encore joignable 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é dans la catégorie "encore joignable". (Il y en a 4 autres, qui sont très similaires, mais de tailles variables)

 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)

Catch: Une fois que j'ai exécuté mon programme, il ne donnait aucune fuite de mémoire, mais il y avait une ligne supplémentaire dans la sortie Valgrind, qui n'était pas présente auparavant:

Suppression de symboles à 0x5296fa0-0x52af438 dans /lib/libgcc_s-4.4.4-20100630.so.1 en raison de munmap ()

Si la fuite ne peut pas être corrigée, quelqu'un au moins peut-il expliquer pourquoi la ligne munmap () amène Valgrind à signaler 0 les fuites "toujours accessibles"?

Edit:

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

Courir avec:

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

Il existe plusieurs façons de définir une "fuite de mémoire". En particulier, il existe deux définitions principales de "fuite de mémoire" qui sont couramment utilisées par les programmeurs.

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

Une définition sans doute plus stricte (et plus utile) de "fuite de mémoire" est la suivante: "La mémoire a été allouée et ne peut pas être libérée par la suite car le programme n'a plus pointeurs vers le bloc de mémoire alloué. " En d'autres termes, vous ne pouvez pas libérer de la mémoire sur laquelle vous n'avez plus de pointeur. Une telle mémoire est donc une "fuite de mémoire". Valgrind utilise cette définition plus stricte du terme "fuite de mémoire". C’est le type de fuite qui peut potentiellement entraîner un épuisement important du tas, en particulier pour les processus de longue durée.

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'étaient pas libérés, mais ils auraient pu être libérés (si le programmeur l'avait voulu) car le programme gardait toujours une trace des pointeurs sur ces blocs de mémoire.

En général, il n'est pas nécessaire de s'inquiéter des blocs "encore accessibles". Ils ne posent pas le type de problème que peuvent causer true les fuites de mémoire. Par exemple, il n’ya normalement aucun risque d’épuisement du tas de blocs "toujours accessibles". En effet, ces blocs sont généralement des allocations uniques, auxquelles les références sont conservées pendant toute la durée de la vie du processus. Vous pouvez certifier que votre programme libère toute la mémoire allouée , mais il n’ya généralement aucun avantage pratique à le faire, car le système d’exploitation récupérera tous les fichiers. la mémoire du processus après la fin du processus, de toute façon. Contrastez ceci avec vrai fuites de mémoire qui, si elles n'étaient pas corrigées, pourraient entraîner l’épuisement de la mémoire d’un processus s’il était laissé suffisamment longtemps, ou entraînerait simplement une perte de mémoire. processus de consommer beaucoup plus de mémoire que nécessaire.

La seule fois où il est utile de vérifier que toutes les allocations ont la correspondance "libère" est si vos outils de détection des fuites ne peuvent pas dire quels blocs sont "encore accessibles" (mais que Valgrind peut le faire) ou si votre système d'exploitation ne récupère pas tous les éléments. la mémoire d'un processus de terminaison (toutes les plates-formes pour lesquelles Valgrind a été porté pour cela).

338
Dan Moulding

Puisqu'il y a une routine de la famille pthread en bas (mais je ne connais pas celle-là), je suppose que vous avez lancé un thread comme joignable qui a arrêté l'exécution.

Les informations sur l'état de sortie de ce thread restent disponibles 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 car vous pouvez utiliser pthread_join pour y accéder.

Si cette analyse est correcte, lancez ces threads détachés ou joignez-les avant de terminer votre programme.

Edit: J'ai lancé votre programme exemple (après quelques corrections évidentes) et je n'ai pas d'erreur mais les suivantes

==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

Depuis le dl- _ 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, 64bits)

10
Jens Gustedt

Vous ne semblez pas comprendre ce que still reachable veux dire.

N'importe quoi still reachable est pas une fuite. Vous n'avez rien à faire à ce sujet.

7
Employed Russian

Voici une explication appropriée de "toujours accessible":

"Toujours accessible" sont des fuites affectées à des variables globales et statiques locales. Comme valgrind suit les variables globales et statiques, il peut exclure les allocations de mémoire affectées "une fois pour toutes". Une variable globale a attribué une allocation une fois et n'a jamais réaffecté cette allocation n'est généralement pas une "fuite" dans le sens où elle ne croît pas indéfiniment. C'est toujours une fuite au sens strict, mais peut généralement être ignoré à moins que vous ne soyez pédant.

Les variables locales auxquelles sont attribuées des affectations et non libres 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 signalera que working_buf est "toujours accessible - 16k" et que temp_buf est "définitivement perdu - 5k".

3
Abbey Road