Sites


KDE guide de développement

Reading backtraces

Lire les piles d'appels (backtraces)

Une pile d'appels, également appelée trace d'appels (stack trace) ou trace arrière de la pile (stack traceback) est un rapport de la manière dont le programme a appelé différentes fonctions au cours de son exécution. Il est couramment utilisé pendant le débogage interactif et le débogage post mortem. Il peut également être affiché à l'intention de l'utilisateur d'un programme comme faisant partie d'un message d'erreur, que celui-ci peut signaler à un programmeur.

Chaque fonction place un cadre de piles (stack frame) sur la pile contenant ses arguments ainsi que d'autres informations dont elle a besoin pour s'exécuter. Les cadres de piles actifs reflètent un certain point dans le temps pendant l'exécution d'un programme. Une trace de piles permet de suivre la séquence des fonctions imbriquées appelées jusqu'au point où la trace d'appels est générée. Dans un scénario post mortem, la trace d'appels va jusqu'à la fonction où l'erreur s'est produite et l'inclut. Sachez, cependant, que la fonction où l'erreur est survenue peut ne pas être responsable de l'échec ; une erreur pourrait bien avoir été imbriquée dans une fonction plus importante (par exemple, en passant une valeur incorrecte à la fonction où le programme a échoué.

La figure suivante illustre un cadre de piles où « main() » appelée « hello() », laquelle appelé « hi() », laquelle a appelé « readinput() ». Une trace d'appels est susceptible de descendre depuis le dernier appel vers le premier, pour que « readinput() » puisse apparaître en premier lieu.

 

 

Les piles d'appels sont essentielles. Elles peuvent paraître sans signification à vos yeux, mais elles sont capables en fait de contenir une multitude d'informations utiles. Une pile d'appels décrit quelles ont été les fonctions appelées avant la panne, pour que les développeurs puissent repérer dans quelle fonction le dysfonctionnement a commencé. Les adresses mémoire exactes peuvent également aider à localiser les données posant problème, telles qu'un vidage mémoire ou « core dump » (un fichier abandonné lorsqu'un programme échoue, comportant le contenu de la mémoire vive au moment de l'échec). Mais produire des piles d'appels satisfaisantes présente un inconvénient : les bibliothèques et les exécutables occupent beaucoup plus d'espace disque que leurs composants de compteurs optimisés qui ne peuvent pas fournir les informations nécessaires pour produire une pile d'appels.

La boîte de dialogue de panne de KDE (Dr. Konqi) devrait apparaître immédiatement après une panne.

 

KDE Crash Dialog

 


 

 

 

 

 

Ouvrir l'onglet « Informations sur le développeur » affichera la pile d'appels pertinente. Ce processus pouvant prendre un certain temps et beaucoup de mémoire, l'opération peut soudainement paraitre stagner. Mais voici à quoi devrait ressembler le résultat :

Using host libthread_db library "/lib/libthread_db.so.1".
[Thread debugging using libthread_db enabled]
[New Thread -1232783168 (LWP 7604)]
[KCrash handler]
#6  0x0806be76 in TreeMapItem::parent (this=0x0)
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.h:285
#7  0x08065fea in TreeMapItemList::compareItems (this=0xbfec04a8, item1=0x0,
    item2=0x0)
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.cpp:720
#8  0xb7281619 in QGList::operator== () from /usr/qt/3/lib/libqt-mt.so.3
#9  0x0806d498 in QPtrList<TreeMapItem>::operator== (this=0xbfec04a8,
    list=@0xbfec0468) at /usr/qt/3/include/qptrlist.h:74
#10 0x08062e18 in TreeMapWidget::mousePressEvent (this=0xbfec03ac,
    e=0xbfebff1c)
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/treemap.cpp:1840
#11 0xb7004a63 in QWidget::event () from /usr/qt/3/lib/libqt-mt.so.3
#12 0xb6f6bca7 in QApplication::internalNotify ()
   from /usr/qt/3/lib/libqt-mt.so.3
#13 0xb6f6ca88 in QApplication::notify () from /usr/qt/3/lib/libqt-mt.so.3
#14 0xb7725a84 in KApplication::notify (this=0xbfec055c, receiver=0xbfec03ac,
    event=0xbfebff1c)
    at /home/bram/KDE/kde3/kdelibs/kdecore/kapplication.cpp:550
#15 0xb6f0bfd2 in QETWidget::translateMouseEvent ()
   from /usr/qt/3/lib/libqt-mt.so.3
#16 0xb6f0b8b0 in QApplication::x11ProcessEvent ()
   from /usr/qt/3/lib/libqt-mt.so.3
#17 0xb6f1b761 in QEventLoop::processEvents () from /usr/qt/3/lib/libqt-mt.so.3
#18 0xb6f82831 in QEventLoop::enterLoop () from /usr/qt/3/lib/libqt-mt.so.3
#19 0xb6f826b6 in QEventLoop::exec () from /usr/qt/3/lib/libqt-mt.so.3
#20 0xb6f6b72f in QApplication::exec () from /usr/qt/3/lib/libqt-mt.so.3
#21 0x0805181e in main (argc=134673960, argv=0xffffffff)  
    at /home/bram/KDE/kde3/kdeaddons/konq-plugins/fsview/main.cpp:55  

Dans cette pile d'appels, le premier cadre de piles est affiché sur la ligne n°6. Du fait que la pile est déroulée depuis la fin jusqu'au début, on peut voir que l'appel qui a arrêté brutalement le programme était « parent() », qui a été appelé par « compareItems() » à la ligne n°7, lequel à son tour a été appelé par l'opérateur surchargé == sur la ligne n°8 et ainsi de suite.

Après le numéro de ligne, le nombre hexadécimal commençant chaque ligne est l'adresse en mémoire où le cadre d'appels démarre pour chaque fonction. À moins que vous n'ayez un vidage mémoire (core dump), celui-ci ne vous est d'aucune utilité. Plus intéressantes sont les listes d'arguments et les adresses de leurs données entre parenthèses. Ainsi, la ligne n°6 montre que « parent() » a été appelée avec un argument unique, « this », dont la valeur est 0 (0x0 en hexadécimal). Naturellement, le nom « this » est affectée à l'objet sur lequel la méthode a été exécutée. Ainsi la méthode « parent() » a été  effectivement appelée sans arguments. Les méthodes, dans les langages orientés objet, sont passées par le pointeur vers l'objet sur lequel elles ont été exécutées en tant que leur premier argument. Donc, « compareItems() » sur la ligne n°7 a été appelée avec deux arguments, mais parce que « this » a été passée comme premier argument, il en existe trois affichées entre parenthèses.

Sur la ligne n°6, la chaîne « (this=0x0) » indique que la fonction « parent() » est appelée avec un pointeur NULL. Bien sûr, n'importe quel programme « plantera » s'il essaie d'y récupérer des données ou de placer des données dans une adresse à laquelle il n'a pas accès. Comme l'adresse 0x0 sur pratiquement tous les systèmes informatiques est réservée et indisponible pour le programme, vous pouvez indiquer que lire à partir de, ou écrire vers, un pointeur NULL provoquera un « plantage ». On peut également voir, dans la documentation de la fonction Qt « parent() », qu'elle est appelée sans arguments (donc le problème n'était pas causé par un argument incorrect) et retourne un pointeur vers le parent de l'objet sur lequel il est appelé. Par conséquent, le développeur devra essayer de découvrir quel objet « parent() » a été appelé et pourquoi il n'a pas été possible de retourner le parent.

 

Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.

Vous devriez rafraîchir la page.