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 " Toujours 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 n'a donné 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 des syms à 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 peut-il au moins expliquer pourquoi la ligne munmap () amène Valgrind à signaler 0 fuites «encore accessibles»?
Éditer:
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
Réponses:
Il existe plusieurs façons de définir la «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 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 soutiennent (à juste titre) que certains types de fuites de mémoire qui correspondent à cette définition ne posent en fait aucun problème et ne devraient donc pas être considérés comme de véritables «fuites de mémoire».
Une définition sans doute plus stricte (et plus utile) de la «fuite de mémoire» est: «La mémoire a été allouée et ne peut pas être libérée par la suite parce que le programme n'a plus de 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 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». C'est le type de fuite qui peut potentiellement provoquer un épuisement important du tas, en particulier pour les processus de longue durée.
La catégorie «encore 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 genre de problème que peuvent causer de véritables fuites de mémoire. Par exemple, il n'y a normalement pas de potentiel d'épuisement du tas à partir de blocs «encore accessibles». En effet, ces blocs sont généralement des allocations ponctuelles, 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 toute 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 toute la mémoire du processus après la fin du processus, de toute façon. Comparez cela avec le vrai des fuites de mémoire qui, si elles ne sont pas corrigées, peuvent entraîner un manque de mémoire dans un processus s'il est laissé en cours d'exécution assez longtemps, ou entraîneront simplement une consommation de mémoire beaucoup plus importante que nécessaire.
Probablement le seul moment où il est utile de s'assurer que toutes les allocations ont des "libérations" correspondantes est si vos outils de détection de fuite 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 tout la mémoire d'un processus de fin (toutes les plates-formes sur lesquelles Valgrind a été porté pour cela).
la source
munmap
soit appelé à la suite du déchargement d'un objet partagé. Et toutes les ressources utilisées par l'objet partagé peuvent être libérées avant son déchargement. Cela pourrait expliquer pourquoi les "encore joignables" sont libérés dans l'munmap
affaire. Je spécule juste ici, cependant. Il n'y a pas assez d'informations ici pour être sûr.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 mis fin à 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 l'utiliserpthread_join
pour y accéder.Si cette analyse est correcte, lancez ces threads détachés ou rejoignez-les avant de terminer votre programme.
Edit : J'ai exécuté votre exemple de programme (après quelques corrections évidentes) et je n'ai pas d'erreurs mais les suivantes
Puisque la
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 suppressionvalgrind
. Peut-être que votre système n'est pas à jour ou que votre distribution ne gère pas ces éléments. (Le mien est ubuntu 10.4, 64 bits)la source
Vous ne semblez pas comprendre ce que cela
still reachable
signifie.Tout
still reachable
n'est pas une fuite. Vous n'avez rien à faire.la source
FILE
pointeurs perdus ?Voici une explication correcte de «toujours accessible»:
Les fuites attribuées aux variables globales et statiques-locales sont «toujours accessibles». Parce que valgrind suit les variables globales et statiques, il peut exclure les allocations de mémoire qui sont assignées «une fois et oublie». Une variable globale affectée une allocation une fois et jamais réaffectée 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ée à moins que vous ne soyez pédant.
Les variables locales auxquelles des allocations sont attribuées et non libres sont presque toujours des fuites.
Voici un exemple
Valgrind rapportera working_buf comme "toujours accessible - 16k" et temp_buf comme "définitivement perdu - 5k".
la source
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 initiale, vous devez toujours vous assurer de l'avoir fait.
la source