2009-07-12 13 views
89

Je travaille sur une application multithread, et je veux le déboguer en utilisant GDB.Exécuter une application dans GDB jusqu'à ce qu'une exception se produise

Le problème est, un de mes fils ne cesse de mourir avec le message:

pure virtual method called 
terminate called without an active exception 
Abort 

Je sais la cause de ce message, mais je ne sais pas où, dans mon fil, il se produit. Un backtrace serait vraiment utile. Lorsque j'exécute mon application dans GDB, elle s'arrête chaque fois qu'un thread est suspendu ou repris. Je veux que mon application continue à fonctionner normalement jusqu'à ce que l'un des threads meure avec cette exception, auquel cas tout devrait s'arrêter afin que je puisse obtenir une trace.

+0

Quel est le signal de création de rapports GDB lors d'une pause? vous devriez être en mesure d'exécuter une commande comme 'gérer SIGUSR1 passer noprint nostop' – Hasturkun

Répondre

126

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

Le code excerpt du manuel gdb décrit la fonction de point de reprise.


5.1.3 Réglage catchpoints

Vous pouvez utiliser catchpoints pour provoquer le débogueur d'arrêter pour certains types d'événements de programme, comme les exceptions C ou le chargement d'une bibliothèque partagée. Utilisez la commande catch pour définir un point d'arrêt.

  • capture événement

    Arrêter lorsque événement se produit. événement peut être une des opérations suivantes:

    • jet

      Le lancement d'une exception C++.

    • prises

      La capture d'une exception C++.

    • exec

      Un appel à exec. Ceci est actuellement disponible uniquement pour HP-UX.

    • fourche

      Un appel à fourche. Ceci est actuellement disponible uniquement pour HP-UX.

    • vfork

      Un appel à vfork. Ceci est actuellement disponible uniquement pour HP-UX.

    • charge ou charge libname

      Le chargement dynamique d'une bibliothèque partagée, ou le chargement de la bibliothèque libname. Ceci est actuellement disponible uniquement pour HP-UX.

    • déchargement ou déchargement libname

      Le déchargement d'une bibliothèque partagée chargé dynamiquement, ou le déchargement de la bibliothèque libname. Ceci est actuellement disponible uniquement pour HP-UX.

  • événement tcatch

    Définir un Catchpoint qui est activé uniquement pour un arrêt. Le point de capture est automatiquement supprimé après la première capture de l'événement.

Utilisez la commande info break à la liste des catchpoints actuels.

Il n'y a des limites à C++ la gestion des exceptions (jet de captures et de capture) 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 prises ne sont pas la meilleure façon de débogage la gestion des exceptions: si vous avez besoin de savoir exactement où un exception est levée, il est préférable de s'arrêter avant que le gestionnaire d'exception ne soit appelé, car de cette façon vous pouvez voir la pile avant que le déroulement ne se produise. Si vous définissez un point d'arrêt dans un gestionnaire d'exceptions, il peut être difficile de savoir où l'exception a été déclenchée.

Pour arrêter juste avant l'appel d'un gestionnaire d'exceptions, vous devez avoir une certaine connaissance de l'implémentation. Dans le cas de GNU C++, des exceptions sont déclenchées en appelant une fonction de bibliothèque nommée __raise_exception qui a l'interface ANSI C suivant:

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

Pour rendre les prises de débogage toutes les exceptions avant que le déroulement de la pile a lieu, définir un point d'arrêt sur __raise_exception (voir section Breakpoints, points de vue et exceptions).

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

+0

S'il vous plaît avoir la 100e upvote. – YSC

5

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

+0

Dans la réponse @JeffreyHill, il est appelé __cxa_pure_virtual maintenant. Je ne sais pas comment vérifier cela moi-même, donc je ne veux pas éditer la réponse. Je n'ai pas l'intention de voter en bas, mais la réponse pourrait être fausse maintenant et devrait être éditée par quelqu'un qui sait ce qui est correct. –

3

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

__cxa_pure_virtual