GNU/Linux >> Tutoriels Linux >  >> Linux

Création et débogage de fichiers de vidage Linux

Crash dump, memory dump, core dump, system dump... produisent tous le même résultat :un fichier contenant l'état de la mémoire d'une application à un moment précis, généralement lorsque l'application plante.

Savoir comment gérer ces fichiers peut vous aider à trouver la ou les causes profondes d'une panne. Même si vous n'êtes pas développeur, les fichiers de vidage créés sur votre système peuvent être très utiles (et accessibles) pour comprendre les logiciels.

Il s'agit d'un article pratique. Pouvez-vous suivre l'exemple en clonant l'exemple de dépôt d'application avec :

git clone https://github.com/hANSIc99/core_dump_example.git

Comment les signaux sont liés aux vidages

Plus de ressources Linux

  • Aide-mémoire des commandes Linux
  • Aide-mémoire des commandes Linux avancées
  • Cours en ligne gratuit :Présentation technique de RHEL
  • Aide-mémoire sur le réseau Linux
  • Aide-mémoire SELinux
  • Aide-mémoire sur les commandes courantes de Linux
  • Que sont les conteneurs Linux ?
  • Nos derniers articles Linux

Les signaux sont une sorte de communication interprocessus entre le système d'exploitation et les applications utilisateur. Linux utilise les signaux définis dans la norme POSIX. Sur votre système, vous pouvez trouver les signaux standards définis dans /usr/include/bits/signum-generic.h . Il existe également une page de signal man informative si vous souhaitez en savoir plus sur l'utilisation des signaux dans votre application. En termes simples, Linux utilise des signaux pour déclencher d'autres activités selon qu'elles étaient attendues ou inattendues.

Lorsque vous quittez une application en cours d'exécution, l'application reçoit généralement le SIGTERM signal. Étant donné que ce type de signal de sortie est attendu, cette action ne créera pas de vidage mémoire.

Les signaux suivants entraîneront la création d'un fichier de vidage (source :bibliothèque GNU C) :

  • SIGFPE :Opération arithmétique erronée
  • SIGILL :instruction illégale
  • SIGSEGV :Accès non valide au stockage
  • SIGBUS :erreur de bus
  • SIGABRT :une erreur détectée par le programme et signalée en appelant abort
  • SIGIOT :étiqueté archaïque sur Fedora, ce signal utilisé pour se déclencher sur abort() sur un PDP-11 et mappe maintenant vers SIGABRT

Création de fichiers de vidage

Accédez au core_dump_example répertoire, exécutez make , et exécutez l'exemple avec le -c1 commutateur :

./coredump -c1

L'application doit se terminer à l'état 4 avec une erreur :

"Abgebrochen (Speicherabzug geschrieben)" se traduit approximativement par "Défaut de segmentation (core dumped)".

La création ou non d'un vidage mémoire est déterminée par la limite de ressources de l'utilisateur exécutant le processus. Vous pouvez modifier les limites de ressources avec le ulimit commande.

Vérifiez le paramètre actuel pour la création d'un vidage mémoire :

ulimit -c

S'il affiche unlimited , alors il utilise la valeur par défaut (recommandée). Sinon, corrigez la limite avec :

ulimit -c unlimited

Pour désactiver la création de type de vidage mémoire :

ulimit -c 0

Le nombre spécifie la ressource en kilo-octets.

Que sont les vidages mémoire ?

La façon dont le noyau gère les vidages mémoire est définie dans :

/proc/sys/kernel/core_pattern

J'utilise Fedora 31 et sur mon système, le fichier contient :

/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

Cela montre que les vidages de mémoire sont transmis au systemd-coredump utilitaire. Le contenu de core_pattern peut varier considérablement entre les différentes versions des distributions Linux. Lorsque systemd-coredump est en cours d'utilisation, les fichiers de vidage sont enregistrés compressés sous /var/lib/systemd/coredump . Vous n'avez pas besoin de toucher directement les fichiers; à la place, vous pouvez utiliser coredumpctl . Par exemple :

coredumpctl list

affiche tous les fichiers de vidage disponibles enregistrés sur votre système.

Avec coredumpctl dump , vous pouvez récupérer les informations du dernier fichier de vidage enregistré :

[stephan@localhost core_dump_example]$ ./coredump 
Application started…

(…….)

Message: Process 4598 (coredump) of user 1000 dumped core.

Stack trace of thread 4598:
#0 0x00007f4bbaf22625 __GI_raise (libc.so.6)
#1 0x00007f4bbaf0b8d9 __GI_abort (libc.so.6)
#2 0x00007f4bbaf664af __libc_message (libc.so.6)
#3 0x00007f4bbaf6da9c malloc_printerr (libc.so.6)
#4 0x00007f4bbaf6f49c _int_free (libc.so.6)
#5 0x000000000040120e n/a (/home/stephan/Dokumente/core_dump_example/coredump)
#6 0x00000000004013b1 n/a (/home/stephan/Dokumente/core_dump_example/coredump)
#7 0x00007f4bbaf0d1a3 __libc_start_main (libc.so.6)
#8 0x000000000040113e n/a (/home/stephan/Dokumente/core_dump_example/coredump)
Refusing to dump core to tty (use shell redirection or specify — output).

Cela montre que le processus a été arrêté par SIGABRT . La trace de la pile dans cette vue n'est pas très détaillée car elle n'inclut pas les noms de fonction. Cependant, avec coredumpctl debug , vous pouvez simplement ouvrir le fichier de vidage avec un débogueur (GDB par défaut). Tapez bt (abréviation de backtrace) pour obtenir une vue plus détaillée :

Core was generated by `./coredump -c1'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50  return ret;
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007fc37a9aa8d9 in __GI_abort () at abort.c:79
#2  0x00007fc37aa054af in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fc37ab14f4b "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007fc37aa0ca9c in malloc_printerr (str=str@entry=0x7fc37ab130e0 "free(): invalid pointer") at malloc.c:5339
#4  0x00007fc37aa0e49c in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:4173
#5  0x000000000040120e in freeSomething(void*) ()
#6  0x0000000000401401 in main ()

Les adresses mémoire :main() et freeSomething() sont assez faibles par rapport aux trames suivantes. En raison du fait que les objets partagés sont mappés sur une zone à la fin de l'espace d'adressage virtuel, vous pouvez supposer que le SIGABRT a été causé par un appel dans une bibliothèque partagée. Les adresses mémoire des objets partagés ne sont pas constantes entre les appels, donc c'est tout à fait correct lorsque vous voyez des adresses variables entre les appels.

La trace de la pile montre que les appels suivants proviennent de malloc.c , ce qui indique que quelque chose avec la (dés)allocation de mémoire a pu mal tourner.

Dans le code source, vous pouvez voir (même sans aucune connaissance en C++) qu'il a tenté de libérer un pointeur, qui n'a pas été renvoyé par une fonction de gestion de la mémoire. Cela entraîne un comportement indéfini et provoque le SIGABRT :

void freeSomething(void *ptr){
    free(ptr);
}
int nTmp = 5;
int *ptrNull = &nTmp;
freeSomething(ptrNull);

L'utilitaire systemd coredump peut être configuré sous /etc/systemd/coredump.conf . La rotation du nettoyage des fichiers de vidage peut être configurée dans /etc/systemd/system/systemd-tmpfiles-clean.timer .

Vous pouvez trouver plus d'informations sur coredumpctl sur sa page de manuel.

Compiler avec des symboles de débogage

Ouvrez le Makefile et commentez la dernière partie de la ligne 9. Elle devrait maintenant ressembler à :

CFLAGS =-Wall -Werror -std=c++11 -g

Le -g Le commutateur permet au compilateur de créer des informations de débogage. Démarrez l'application, cette fois avec le -c2 commutateur :

./coredump -c2

Vous obtiendrez une exception en virgule flottante. Ouvrez le dump dans GDB avec :

coredumpctl debug

Cette fois, vous êtes dirigé directement vers la ligne du code source qui a provoqué l'erreur :

Reading symbols from /home/stephan/Dokumente/core_dump_example/coredump…
[New LWP 6218]
Core was generated by `./coredump -c2'.
Program terminated with signal SIGFPE, Arithmetic exception.
#0 0x0000000000401233 in zeroDivide () at main.cpp:29
29 nRes = 5 / nDivider;
(gdb)

Tapez list pour avoir un meilleur aperçu du code source :

(gdb) list
24      int zeroDivide(){
25          int nDivider = 5;
26          int nRes = 0;
27          while(nDivider > 0){
28              nDivider--;
29              nRes = 5 / nDivider;
30          }
31          return nRes;
32      }

Utilisez la commande info locals pour récupérer les valeurs des variables locales à partir du moment où l'application a échoué :

(gdb) info locals
nDivider = 0
nRes = 5

En combinaison avec le code source, vous pouvez voir que vous avez rencontré une division par zéro :

nRes = 5 / 0

Conclusion

Savoir comment gérer les fichiers de vidage vous aidera à trouver et à corriger des bogues aléatoires difficiles à reproduire dans une application. Et s'il ne s'agit pas de votre application, transmettre un vidage mémoire au développeur l'aidera à trouver et à résoudre le problème.


Linux
  1. Trouver des fichiers et des répertoires sous Linux comme un pro

  2. Créer, supprimer et gérer des répertoires sous Linux

  3. Trouvez les fichiers et répertoires les plus volumineux sous Linux

  4. Linux – Répertoires standard et/ou communs sur les systèmes Unix/linux ?

  5. Création et suppression de fichiers et de répertoires sous Linux

Comment compresser des fichiers et des répertoires sous Linux

Pigz - Compresser et décompresser des fichiers en parallèle sous Linux

Comment installer Rclone sous Linux et Unix

Économisez de l'espace en compressant les fichiers et les dossiers sous Linux

Trouvez facilement des fichiers et des répertoires sur Linux

Partage de fichiers entre Linux Mint et Windows 10