2016-12-29 6 views
0

Ich habe ein Problem mit Ausnahmen in Multithreaded C++ - Code. Das folgende Programm wird mit terminate called without an active exception Aborted (core dumped) beendet.Std :: Thread und Exception-Behandlung

#include <thread> 
#include <iostream> 
#include <stdexcept> 

struct Thing { 

    void runComponent() 
    { 
     throw std::runtime_error("oh no!\n"); 
    } 

    void runController() 
    { 
     while (true) {} 
    } 

    void run() 
    { 
     auto control_thread = std::thread([this] { runController(); }); 

     runComponent(); 

     if (control_thread.joinable()) 
      control_thread.join(); 
    } 
}; 

int main() 
{ 
    try { 
     Thing thing; 
     thing.run(); 
    } catch (std::runtime_error &ex) { 
     std::cerr << ex.what(); 
    } 
} 

Stattdessen würde Ich mag die Ausnahme im try catch Block in main() zu handhaben. Ich verstehe, dass Ausnahmen (normalerweise) nicht zwischen Threads übergeben werden, da Threads jeweils einen eigenen Stack haben. Das Problem hier (so scheint es mir) ist, dass die Ausnahme nicht behandelt wird, obwohl sie auf dem nicht gespaltenen Thread generiert wird. Wenn ich die Zeilen in run() mit control_thread kommentieren, funktioniert alles gut.

Zusammengestellt mit clang-3.8 und -std=c++11 main.cpp -lpthread.

+0

@Curious Vielleicht. Ich kenne 'exception_ptr'. Aber das Problem hier (denke ich ..) ist, dass Werfer (runComponent) tatsächlich auf dem Hauptthread ist. Muss ich den Ausnahmezeiger auch in diesem Fall verwenden? – jonnew

+0

Beantwortet in der Antwort unten! Ich habe die Frage falsch verstanden – Curious

Antwort

1

Das Problem hier ist, dass Sie detach() oder join() für den Thread nicht aufrufen, den Sie in der Methode run() erstellen. Das ist ein Fehler in C++ - Threads. Siehe When should I use std::thread::detach?

Wenn Sie Ihren Code entweder auf dem alles folgenden ändern dann funktioniert

#include <thread> 
#include <iostream> 
#include <stdexcept> 

struct Thing { 

    void runComponent() 
    { 
     throw std::runtime_error("oh no!\n"); 
    } 

    void runController() 
    { 
     return; 
    } 

    void run() 
    { 
     auto control_thread = std::thread([this] { runController(); }); 
     // either of the following two will work 
     // control_thread.join(); 
     control_thread.detach(); 

     runComponent(); 
    } 
}; 

int main() 
{ 
    try { 
     Thing thing; 
     thing.run(); 
    } catch (std::runtime_error &ex) { 
     std::cerr << ex.what(); 
    } 
} 

Es sah aus wie das, was Sie wollten ein detach war, das ist, warum ich den Faden in dem obigen Beispiel abgelöst. Wenn das nicht das ist, was Sie wollen, benötigen Sie wahrscheinlich einen anderen Weg, um mit dem Thread umzugehen. Wenn Sie möchten, dass der Haupt-Thread und der andere Thread unabhängig voneinander funktionieren, benötigen Sie eine andere Synchronisierung.

+0

Ja, das funktioniert. Ich denke, ich möchte trennen, aber ich bemerke den Punkt, der in der Antwort auf den SO-Link, den Sie bereitstellen, angesprochen wird, es sei denn, Sie benötigen mehr Flexibilität und sind bereit, einen Synchronisationsmechanismus bereitzustellen, um auf die Thread-Vervollständigung zu warten Fall, den Sie verwenden können, trennen Sie ". In diesem speziellen Fall, was bedeutet das? Werden die von 'runController()' zugewiesenen Ressourcen freigegeben, wenn ich detachiere? – jonnew

+0

Auch mit "Fehler in C++ Threads" meinst du in der Standard-Bibliothek Implementierung? – jonnew

+0

@jonnew Ich denke, was das bedeutet ist, dass, wenn Sie einige benutzerdefinierte Möglichkeit, Ausnahmen behandeln möchten, müssen Sie es manuell mit Sperren implementieren. Am einfachsten wäre es, eine Liste von Threads zu erstellen, die Thread-IDs für die Threads in der Reihenfolge haben, in der Ausnahmen aufgetreten sind. Ich glaube nicht, dass es relevant ist – Curious

Verwandte Themen