Comment trouver une fuite de mémoire d'un processus en cours?

19

Existe-t-il un moyen, je peux trouver la fuite de mémoire d'un processus en cours? Je peux utiliser Valgrind pour trouver des fuites de mémoire avant le début d'un processus. Je peux utiliser GDB pour l'attacher à un processus en cours. Comment pourrais-je déboguer une fuite de mémoire d'un processus en cours?

howtechstuffworks
la source
Valgrind est très utile, je l'appellerais même intuitif.
user400344

Réponses:

13

Voici les étapes presque garanties pour trouver qui fuit la mémoire:

  1. Découvrez le PID du processus qui provoque la fuite de mémoire.

    ps -aux
  2. capturer le /proc/PID/smapset enregistrer dans un fichier comme BeforeMemInc.txt.

  3. attendez que la mémoire augmente.
  4. capturer à nouveau /proc/PID/smapset l'enregistrer aafterMemInc.txt
  5. trouver la différence entre le premier smapset le deuxième smaps, par exemple avec

    diff -u beforeMemInc.txt afterMemInc.txt

  6. notez la plage d'adresses où la mémoire a été augmentée, par exemple:

       beforeMemInc.txt            afterMemInc.txt
    ---------------------------------------------------
    2b3289290000-2b3289343000   2b3289290000-2b3289343000  #ADDRESS
    Shared_Clean:    0 kB       Shared_Clean:    0 kB          
    Shared_Dirty:    0 kB       Shared_Dirty:    0 kB
    Private_Clean:   0 kB       Private_Clean:   0 kB
    Private_Dirty:  28 kB       Private_Dirty:  36 kB  
    Referenced:     28 kB       Referenced:     36 kB
    Anonymous:      28 kB       Anonymous:      36 kB  #INCREASE MEM
    AnonHugePages:   0 kB       AnonHugePages:   0 kB
    Swap:            0 kB       Swap:            0 kB
    KernelPageSize:  4 kB       KernelPageSize:  4 kB
    MMUPageSize:     4 kB       MMUPageSize:     4 kB
    Locked:          0 kB       Locked:          0 kB
    VmFlags: rd wr mr mw me ac  VmFlags: rd wr mr mw me ac
  7. utiliser GDB pour vider la mémoire sur le processus en cours ou obtenir le coredump en utilisant gcore -o process

  8. J'ai utilisé gdb lors de l'exécution du processus pour vider la mémoire dans un fichier.

    gdb -p PID
    dump memory ./dump_outputfile.dump 0x2b3289290000 0x2b3289343000
  9. maintenant, utilisez la stringscommande ou hexdump -Cpour imprimer ledump_outputfile.dump

    strings outputfile.dump
  10. Vous obtenez un formulaire lisible où vous pouvez localiser ces chaînes dans votre code source.

  11. Analysez votre source pour trouver la fuite.

Jagannath Pattar
la source
12

Je pense que memleax est exactement ce que vous voulez.

Il débogue la fuite de mémoire d'un processus en cours d'exécution en l'attachant, sans recompiler le programme ni redémarrer le processus cible. C'est très pratique et adapté à l'environnement de production.

Il fonctionne sur GNU / Linux et FreeBSD.

REMARQUE: je suis l'auteur, toute suggestion est la bienvenue

== EDIT ==

J'écris un autre outil libleak , qui accroche les fonctions mémoire par LD_PRELOAD.

Il n'est pas non plus nécessaire de modifier le programme cible. Bien que vous deviez redémarrer la progression avec LD_PRELOAD, vous pouvez activer / désactiver la détection pendant l'exécution.

Il y a beaucoup moins d'impact sur les performances, car aucun piège de signal.

Comparé à des outils similaires (tels que mtrace), il imprime la pile complète d'appels à un point de fuite de mémoire suspect.

Bingzheng Wu
la source
1
Je me porte garant pour memleax comme un outil très utile pour surveiller les fuites évidentes. Les résumés de sortie sont étonnamment efficaces . Presque comme si je les écrivais si j'avais la puissance de traitement pour le faire manuellement. Merci pour ce
sehe
6

Sous Linux, vous pouvez activer mtrace dans votre programme, mais c'est un changement de code.

Sur OpenBSD, vous pouvez essayer les statistiques malloc .

Le vérificateur de fuite de Google pourrait également valoir le coup d'œil, et contrairement à mtrace, vous pouvez être en mesure d'utiliser LD_PRELOADpour éviter la recompilation.

Inutile
la source
0

Je pense que sans fournir de support pour la surveillance d'allocation après le démarrage du programme directement dans le code source, vous n'avez pas de chance. Voici deux raisons auxquelles je peux penser:

  • Les vérificateurs de tas s'initialisent lorsque le programme démarre. Certains offrent la possibilité de modifier le timing exact, mais les variables d'environnement qui les démarrent doivent être définies lors de l'exécution du programme. En effet, ils veillent à ce que chaque allocation ait une désallocation correspondante, et ils en manqueraient autrement.
  • La vérification des segments de mémoire nécessite généralement des privilèges élevés, ou hooks, fournis par le système d'exploitation. Si ces crochets ne sont pas fournis au moment du démarrage du programme, les vérificateurs de tas ne peuvent pas les exploiter. Je ne crois pas que les OS offrent ces privilèges après le démarrage du programme en question.

Si, toutefois, votre programme s'exécute à l'intérieur d'une machine virtuelle, cet environnement peut prendre en charge la surveillance des allocations. Je sais que Java dispose de plusieurs outils de surveillance d'allocation et de récupération de place (comme visualVM ) qui se connectent aux programmes en cours d'exécution ou aux machines virtuelles.

Chris Betti
la source
0

Purify d'IBM est probablement l'outil le plus ancien et le plus sophistiqué de tous. Il marquera le numéro de ligne dans le code qui provoque la fuite de mémoire.

équilibre de vie
la source