boost::thread exception problem



  • hej leute, hab da mal ne frage:
    weis jemand warum mir mein kleines program eine excetion wirft?

    #include <iostream>
    
    #include <boost/thread.hpp>
    
    void thread(int number) {
      std::cout << number << std::endl;
      return;
    }
    
    int main() {
      for(int i=0; i< 10000000 ; i++) {
        boost::thread(boost::bind(&::thread, i));
        boost::this_thread::sleep(boost::posix_time::microseconds(1000));
      }
    }
    

    irgendwan bricht das program ab mit

    terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::thread_resource_error> >'
    

    auch bei

    int main() {
      boost::thread *t;
      for(int i=0; i< 10000000 ; i++) {
        t = new boost::thread(boost::bind(&::thread, i));
        t->interrupt();
        delete t;
      }
    }
    

    aber bei

    int main() {
      boost::thread *t;
      for(int i=0; i< 10000000 ; i++) {
        t = new boost::thread(boost::bind(&::thread, i));
        t->join();
        delete t;
      }
    }
    

    läuft das program durch!!! 😕
    räumt boost thread nur bei einem join richtig hintersich auf???



  • Darf man fragen, wieso du die Threads am Heap erzeugst? (Abgesehen davon, dass du das delete völlig weglässt.)
    Ich vermute, dass dir dein OS nicht erlaubt, so viele Threads zu erstellen.

    Edit: Außerdem solltest du die Zugriffe auf std::cout synchronisieren.



  • hej 314159265358979 danke erstmal für deine antwort.

    Darf man fragen, wieso du die Threads am Heap erzeugst?

    wie erzeugt man den einen thread???

    Abgesehen davon, dass du das delete völlig weglässt.

    das war ein tipfehler... im ersten listing gibt es kein new (habs editiert jetzt), somit ist ein delete auch nicht nötig.

    Außerdem solltest du die Zugriffe auf std::cout synchronisieren.

    im originalcode ist es synchronisiert. das ist nur ein kleiner test.

    irgend eine idee?



  • Ganz einfach, du erzeugst unnötig viele Threads, lass das einfach bleiben. 😉
    Ich würde die Threads einfach in einem std::vector speichern.



  • 😃 lol
    netter Ansatz, lösst mein problem aber nicht ganz...

    Edit: außer das mit vectoren vllt



  • Ich würde mal vermuten, der Thread ist noch nicht mit seiner Arbeit fertig, wenn du das thread-Objekt (in Listing 1 implizit beim Verlassen des Scopes, im Listing 2 explizit durch delete) zerstörst - und versucht anschießend noch etwas dort reinzuschreiben. Lösung des Problems: Das Objekt muß so lange überleben, bis du sicher bist, daß der Thread fertig ist.

    PS: Was willst du eigentlich mit 10 Millionen Threads erreichen, die alle nichts anderes machen als etwas auszugeben und sich dann zu beenden? Normalerweise nutzt man Threads eher, wenn man eine langwierige Arbeit "nebenher" erledigen will.



  • Stell dein Programm mal in einen try Block und füge darunter sowas hinzu, wie

    catch(const std::exception& ex)
    {
        // Benötigt #include <boost/exception/diagnostic_information.hpp>
        std::cerr << boost::diagnostics_information(ex) << std::endl;
    }
    

    Dann müssen wir nicht raten.



  • Ich lese aus einer Datenbank Zeiten aus und steuere mit dem prog dann diverse sachen zu bestimmten Zeiten. Das problem habe ich schon konzeptuell gelösst gehabt... 🙄 (hab statt vor erzeugung vom thread, erst im thread danach geschaut ob es ausgeführt werden soll oder nicht 👎 )... mich hats nur gewundert warum da eine exception geworfen wird und deswegen dieser beitrag hier.

    im übrigen wird bei

    void thread(int number) {
      std::cout << number;
      boost::this_thread::sleep(boost::posix_time::seconds(1));
      std::cout << std::endl;
      return;
    }
    
    int main() {
      boost::thread *t;
      for(int i=0; i< 10000000 ; i++) {
        t = new boost::thread(boost::bind(&::thread, i));
        t->interrupt();
        t->join(); // auf rat von CStoll
        delete t;
      }
    }
    

    auch keine exception geworfen. Unterbreche, aber warte trotzdem mit join ab bis ein interruption-point erreicht wird (ist in sleep zum Beispiel schon vordefiniert ist.)



  • Oberon_0 schrieb:

    Stell dein Programm mal in einen try Block und füge darunter sowas hinzu, wie

    catch(const std::exception& ex)
    {
        // Benötigt #include <boost/exception/diagnostic_information.hpp>
        std::cerr << boost::diagnostics_information(ex) << std::endl;
    }
    

    Dann müssen wir nicht raten.

    bringt glaube ich nicht mehr als meine meldung.

    Throw in function (unknown)
    Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::thread_resource_error> >
    std::exception::what: boost::thread_resource_error
    


  • @pi88el:
    Boost.Thread räumt auch bei einem "detach" (was der Destruktor automatisch macht) hinter sich auf.
    Allerdings erzeugst du in den ersten beiden Beispielen "unendlich viele" Threads, ohne auf deren Beendigung zu warten.
    Da das Scheduling (wann läuft welcher Thread) nicht deterministisch ist, kannst du nicht garantieren, dass nicht der Speicher ausgeht (oder sonstige Systemresourcen).



  • pi88el schrieb:

    auch keine exception geworfen. Unterbreche, aber warte trotzdem mit join ab bis ein interruption-point erreicht wird (ist in sleep zum Beispiel schon vordefiniert ist.)

    Erstens wartet join() nicht auf den nächsten Unterbrechungspunkt, sondern auf das Thread-Ende (das heißt, danach ist es sicher, das thread-Objekt zu vernichten).
    Zweitens bin ich mir nicht sicher, ob du mit der Kombination aus interrupt() und join() nicht einen Deadlock verursachen könntest.
    Und drittens hast du immer nich nicht erklärt, wozu du so viele kurzlebige Mikro-Threads auf einen Haufen benötigst.



  • CStoll schrieb:

    Zweitens bin ich mir nicht sicher, ob du mit der Kombination aus interrupt() und join() nicht einen Deadlock verursachen könntest.

    Wo vermutest du ein Problem?
    interrupt() setzt lediglich ein Flag, und kehrt dann sofort zurück.
    Also kann man mit interrupt() keinen Deadlock basteln.

    Mit join() dagegen geht das schon, aber ganz unabhängig von interrupt().



  • Wie gesagt, ich war mir da nicht sicher, was der angesprochene Thread mit diesem Flag macht. Da bin ich aus der Boost-Doku nicht so richtig schlau geworden, ob der Thread nicht dadurch auf Eis gelegt wird.


Anmelden zum Antworten