2009-10-30 15 views
2

J'ai ce morceau de code ici:Segmentation fault lors de la capture des exceptions dans une application liée à libpthread (linux, C++)

Ces fonctions sont utilisées pour créer et arrêter un pthread:

void WatchdogController::conscious_process_handler_start() { 

    if (debug) cout << "WatchdogController: starting conscious process thread" << endl; 

    cn_pr_thread_active = true; 

    if (pthread_create(&cn_pr_thread, NULL, conscious_process_handler, this) < 0) { 
     cn_pr_thread_active = false; 
     throw WatchdogException("Unable to start new thread"); 
    } 
} 

void WatchdogController::conscious_process_handler_stop() { 

    if (debug) cout << "WatchdogController: stopping conscious process thread" << endl; 

    cn_pr_thread_active = false; 

    int *retval; 

    pthread_join(cn_pr_thread, (void **)&retval); 

    if (*retval < 0) { 
     delete retval; 
     string err = string("Error returned by conscious_process_handler(): ") + string(pthread_err); 
     throw WatchdogException(err.c_str()); 
    } 

    delete retval; 
} 

J'utilise select() dans la fonction transmise à pthread, et lorsqu'il est stoppé, il renvoie une erreur résultant de la valeur négative de pthread, mais ce n'est pas le problème, je le corrigerai plus tard - le problème est que lorsque l'exception est lancée ici:

throw WatchdogException(err.c_str()); 

et pris ici:

try { 
     watchdog_controller->hardware_watchdog_stop(); 
     watchdog_controller->unconscious_process_handler_stop(); 
     watchdog_controller->conscious_process_handler_stop(); 
    } 
    catch (HardwareWatchdogException &e) { 
     cerr << "Error stopping hardware watchdog!" << endl; 
     cerr << e.get_reason() << endl; 
     string err = string("Exception thrown by hardware watchdog controller") + string(e.get_reason()); 
     if (log) write_log(err.c_str()); 
     delete watchdog_controller; 
     return -1; 
    } 
    catch (WatchdogException &e) { 
     cerr << "Exception cought when exiting!" << endl; 
     cerr << e.get_reason() << endl; 
     string err = string("Exception cought when exiting") + string(e.get_reason()); 
     if (log) write_log(err.c_str()); 
     delete watchdog_controller; 
     return -1; 
    } 

je reçois une erreur de segmentation puis essayez d'accéder à l'objet à ce stade:

cerr << e.get_reason() << endl; 

Quelle pourrait être la raison?

Référence & e indique quelque chose, mais il semble que l'adresse était invalide.

est ici la classe d'exception:

class WatchdogException { 

    public: 

     /** 
      @brief  Default constructor 
     */ 
     WatchdogException() : reason() { 
     } 

     /** 
      @brief  Overloaded constructor - setting the error message 
      @param  why   Error message 
     */ 
     WatchdogException(const char *why) : reason(why) { 
     } 

     /** 
      @brief  The destructor 
     */ 
     virtual ~WatchdogException() { 
     } 

     /** 
      @brief  A getter for the error message 
      @return  Returns a string containing error description 
     */ 
     virtual std::string get_reason() const { 
      return reason; 
     } 

    protected: 

     /** 
      @var  reason  String containing the error message 
     */ 
     std::string reason; 

}; 
+0

cela fait-il une différence si vous l'avez attrapé par const ref? – Naveen

+0

Rien ne me semble aussi faux ici. Pouvez-vous obtenir un backtrace dans gdb? –

+0

Lorsqu'il est exécuté sous gdb, il se bloque sur pthread_join - Je pense que cela a quelque chose à voir avec gdb ne passant pas les signaux correctement - comment configurer gdb pour passer tous les signaux à programmer? – zbigh

Répondre

0

Dans le constructeur de WatchDogException, vous rappelez le pointeur sur le c-chaîne passée ou vous faites une copie de celui-ci.

Si vous stockez simplement le pointeur, alors lorsque "err" est hors de portée lorsque l'exception est levée, le pointeur retourné par c_str() sera mauvais, d'où votre erreur seg lorsque vous essayez de l'utiliser.

+0

WatchDogException effectue une copie interne de la chaîne C, ce n'est donc pas le problème. –

3

Je suppose que vous n'êtes pas correctement allouer de la mémoire pour retval, ou en quelque sorte que vous retournez un pointeur non valide de cn_pr_thread, et c'est la raison pour laquelle vous obtenez une erreur de segmentation lorsque vous appelez pthread_join.

+0

Je passe un pointeur non initialisé, mais j'alloue de la mémoire pour un entier à l'intérieur du thread. Que voulez-vous dire en disant potentiellement? Est-il possible que la fonction dépasse la déclaration throw? – zbigh

+0

Pouvez-vous montrer où vous allouez de la mémoire pour retval? Quant à la double suppression, vous avez raison: elle ne devrait pas dépasser l'instruction throw. Je ne le lisais pas assez attentivement. –

+0

peu importe si vous avez dynamiquement alloué la mémoire pour les données retournées dans le thread, vous avez besoin de quelque chose déjà alloué pour le copier. –