Question

J'essaie de déboguer un problème de fuite de mémoire. J'utilise mtrace () obtenir une trace malloc / free / realloc. J'ai lancé mon prog et j'ai maintenant un énorme fichier journal. Jusqu'ici tout va bien. Mais j'ai du mal à interpréter le fichier. Regardez ces lignes:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502620 0x30
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1501460 0xa64

Ce qui est étrange, c’est qu’un appel (même adresse de retour) est responsable de 4 attributions.

Même étranger:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa2c
…
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80

Entre ces deux lignes, le bloc 0x2aaab43a1700 n'est jamais libéré. ??

Quelqu'un sait-il comment expliquer cela? Comment un appel pourrait-il aboutir à 4 attributions? Et comment malloc pourrait-il renvoyer une adresse déjà attribuée auparavant?

edit 2008/09/30: Le script pour analyser la sortie mtrace () fournie par GLIBC (mtrace.pl) n’aide en rien. Il va juste dire: Alloc 0x2aaab43a1700 en double. Mais comment cela pourrait-il arriver?

Était-ce utile?

La solution

La fonction qui alloue la mémoire est appelée plusieurs fois. L’adresse de l’appelant pointe vers le code qui a fait l’attribution et ce code est simplement exécuté plusieurs fois.

Voici un exemple en C:

void *allocate (void)
{
  return (malloc(1000));
}

int main()
{
  mtrace();
  allocate();
  allocate();
}

Le résultat de mtrace est:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at 0x4004f6
0x0000000000601850    0x3e8  at 0x4004f6

Notez en quoi l’adresse de l’appelant est identique? C’est la raison pour laquelle le script d’analyse mtrace dit qu’elles sont identiques, car le même bogue est observé plusieurs fois, ce qui entraîne plusieurs fuites de mémoire.

La compilation avec les indicateurs de débogage (-g) est utile si vous pouvez:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at /home/andrjohn/development/playground/test.c:6
0x0000000000601850    0x3e8  at /home/andrjohn/development/playground/test.c:6

Autres conseils

Vous examinez le résultat direct de mtrace, qui est extrêmement déroutant et contre-intuitif. Heureusement, il existe un script Perl (appelé mtrace, situé dans glibc-utils) qui peut très facilement aider à l'analyse de cette sortie.

Compilez votre construction avec le débogage et exécutez mtrace comme ceci:

$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out

Memory not freed:
-----------------
   Address     Size     Caller
0x094d9378    0x400  at test.c:6

La sortie devrait être un lot plus facile à digérer.

Une explication possible est que la même fonction alloue différentes tailles de mémoire tampon? Strdup est l’un de ces exemples.

Pour la deuxième question, il est possible que le moteur d’exécution alloue des "& static; static". zone de travail qui ne doit pas être libérée tant que le processus n'est pas terminé. Et à ce stade, le système d’exploitation sera nettoyé après le processus de toute façon.

Pensez-y de cette façon: en Java, il n’existe aucun destructeur ni aucune garantie que la finalisation sera jamais appelée pour aucun objet.

Essayez d’exécuter votre application sous valgrind. Cela vous donnera peut-être une meilleure idée de ce qui est réellement filtré.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top