web-dev-qa-db-fra.com

Exécuter une application dans GDB jusqu'à ce qu'une exception se produise

Je travaille sur une application multithread et je veux la déboguer en utilisant GDB.

Le problème est, l'un de mes fils continue de mourir avec le message:

pure virtual method called
terminate called without an active exception
Abort

Je connais la cause de ce message, mais je ne sais pas où dans mon fil il se produit. Un retour en arrière serait vraiment utile.

Lorsque j'exécute mon application dans GDB, elle s'interrompt chaque fois qu'un thread est suspendu ou repris. Je veux que mon application continue de fonctionner normalement jusqu'à ce que l'un des threads meure avec cette exception, auquel cas tout devrait s'arrêter pour que je puisse obtenir une trace.

96
Ankur Sethi

Vous pouvez essayer d'utiliser un "point de capture" (catch throw) pour arrêter le débogueur au point où l'exception est générée.

Ce qui suit extrait Du manuel de gdb décrit la fonction de point de capture.


5.1.3 Définition des points de capture

Vous pouvez utiliser des points d'arrêt pour provoquer l'arrêt du débogueur pour certains types d'événements de programme, tels que les exceptions C++ ou le chargement d'une bibliothèque partagée. Utilisez la commande catch pour définir un point de capture.

  • catch événement

    Arrêtez lorsque l'événement se produit. l'événement peut être l'un des suivants:

    • jeter

      Le lancement d'une exception C++.

    • capture

      La capture d'une exception C++.

    • exec

      Un appel à l'exéc. Ceci n'est actuellement disponible que pour HP-UX.

    • fork

      Un appel à fork. Ceci n'est actuellement disponible que pour HP-UX.

    • vfork

      Un appel à vfork. Ceci n'est actuellement disponible que pour HP-UX.

    • charger ou charger libname

      Le chargement dynamique de n'importe quelle bibliothèque partagée ou le chargement de la bibliothèque libname. Ceci n'est actuellement disponible que pour HP-UX.

    • décharger ou décharger libname

      Déchargement de toute bibliothèque partagée chargée dynamiquement ou déchargement de la bibliothèque libname. Ceci n'est actuellement disponible que pour HP-UX.

  • événement tcatch

    Définissez un point d'arrêt qui n'est activé que pour un seul arrêt. Le point de capture est automatiquement supprimé après la première capture de l'événement.

Utilisez le info break commande pour lister les points de capture actuels.

Il existe actuellement certaines limitations à la gestion des exceptions C++ (catch throw et catch catch) dans GDB:

* If you call a function interactively, GDB normally returns control to you when the function has finished executing. If the call raises an exception, however, the call may bypass the mechanism that returns control to you and cause your program either to abort or to simply continue running until it hits a breakpoint, catches a signal that GDB is listening for, or exits. This is the case even if you set a catchpoint for the exception; catchpoints on exceptions are disabled within interactive calls.

* You cannot raise an exception interactively.

* You cannot install an exception handler interactively. 

Parfois, catch n'est pas le meilleur moyen de déboguer la gestion des exceptions: si vous avez besoin de savoir exactement où une exception est déclenchée, il est préférable de s'arrêter avant l'appel du gestionnaire d'exceptions, car de cette façon, vous pouvez voir la pile avant tout déroulement. Si vous définissez un point d'arrêt dans un gestionnaire d'exceptions à la place, il peut ne pas être facile de savoir où l'exception a été déclenchée.

Pour arrêter juste avant l'appel d'un gestionnaire d'exceptions, vous avez besoin de connaître l'implémentation. Dans le cas de GNU C++, des exceptions sont levées en appelant une fonction de bibliothèque nommée __raise_exception qui a l'interface C ANSI suivante:

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

Pour que le débogueur intercepte toutes les exceptions avant tout déroulement de pile, définissez un point d'arrêt sur __raise_exception (voir la section Points d'arrêt, points d'observation et exceptions).

Avec un point d'arrêt conditionnel (voir la section Conditions de rupture) qui dépend de la valeur de id, vous pouvez arrêter votre programme lorsqu'une exception spécifique est levée. Vous pouvez utiliser plusieurs points d'arrêt conditionnels pour arrêter votre programme lorsque plusieurs exceptions sont levées.

140
Dan

Définissez un point d'arrêt sur __pure_virtual

5
Steve Folly

FWIW, apparemment, dans gcc 4.1, le nom de fonction approprié a changé et il faut définir un point d'arrêt dans cette fonction.

__cxa_pure_virtual

4
Jeffrey Hill