web-dev-qa-db-fra.com

Terminaison C ++ appelée sans exception active

Je reçois une erreur C++ avec threading:

terminate called without an active exception
Aborted

Voici le code:

#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

template<typename TYPE>
class blocking_stream
{
public:
    blocking_stream(size_t max_buffer_size_)
        :   max_buffer_size(max_buffer_size_)   
    {
    }

    //Push data into the buffer
    blocking_stream &operator<<(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx); 
        while(buffer.size()>=max_buffer_size)
            stop_if_full.wait(mtx_lock);

        buffer.Push(std::move(other));

        mtx_lock.unlock();
        stop_if_empty.notify_one();
        return *this;
    }
    //POP data out of the buffer 
    blocking_stream &operator>>(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx);
        while(buffer.empty())
            stop_if_empty.wait(mtx_lock);

        other.swap(buffer.front()); 
        buffer.pop();

        mtx_lock.unlock();
        stop_if_full.notify_one();
        return *this;
    }

private:
    size_t max_buffer_size;
    std::queue<TYPE> buffer;
    std::mutex mtx;
    std::condition_variable stop_if_empty,
                            stop_if_full;
    bool eof;   
};

J'ai modélisé mon code autour de cet exemple: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

Qu'est-ce que je fais mal et comment puis-je corriger l'erreur?

66
111111

Lorsqu'un objet de fil sort de la portée et qu'il est dans un état pouvant être joint, le programme est terminé. Le comité de normalisation avait deux autres options pour le destructeur d'un fil joignable. Il pourrait rejoindre silencieusement - mais rejoindre pourrait ne jamais revenir si le fil est bloqué. Ou il pourrait détacher le thread (un thread détaché n'est pas joignable). Cependant, les threads détachés sont très délicats, car ils peuvent survivre jusqu'à la fin du programme et gâcher la libération des ressources. Donc, si vous ne voulez pas terminer votre programme, assurez-vous de rejoindre (ou détacher) chaque thread.

92
Bartosz Milewski

Comment reproduire cette erreur:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  return 0;
}

Compiler et exécuter:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
terminate called without an active exception
Aborted (core dumped)

Vous obtenez cette erreur parce que vous n'avez pas rejoint ou déconnecté votre thread.

ne façon de résoudre ce problème, rejoignez le fil comme ceci:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  t1.join();
  return 0;
}

Ensuite, compilez et exécutez:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

L'autre façon de le réparer, détache le comme ceci:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() 
{ 
     {

        std::thread t1(task1, "hello"); 
        t1.detach();

     } //thread handle is destroyed here, as goes out of scope!

     usleep(1000000); //wait so that hello can be printed.
}

Compiler et exécuter:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

Découvrez le détachement de threads C++ et la jonction de threads C++.

37
Eric Leschinski

Eric Leschinski et Bartosz Milewski ont déjà donné la réponse. Ici, je vais essayer de le présenter de manière plus conviviale pour les débutants.

Une fois qu'un thread a été démarré dans une étendue (qui s'exécute elle-même sur un thread), il convient de s'assurer explicitement que l'un des cas suivants se produit avant que le thread ne sorte de l'étendue:

  • Le moteur d'exécution quitte l'étendue uniquement après que le thread a fini de s'exécuter. Ceci est réalisé en rejoignant avec ce fil. Notez le langage, c'est la portée externe qui se joint à ce fil.
  • Le runtime laisse le thread s'exécuter seul. Ainsi, le programme quittera la portée, que ce thread ait fini de s’exécuter ou non. Ce fil s'exécute et quitte par lui-même. Ceci est réalisé en détachant le fil. Cela pourrait entraîner des problèmes, par exemple, si le fil de discussion fait référence à des variables de cette étendue externe.

Notez qu'au moment où le fil est joint ou détaché, son exécution est peut-être bien terminée. Cependant, l’une ou l’autre des opérations doit être effectuée explicitement.

16
haripkannan

Tant que votre programme meurt, alors sans détacher ni rejoindre du thread, cette erreur se produira. Sans détacher ni rejoindre le fil, vous devriez donner une boucle sans fin après la création du fil.

int main(){

std::thread t(thread,1);

while(1){}

//t.detach();
return 0;}

Il est également intéressant de noter que, après avoir dormi ou bouclé, le fil peut être détaché ou joint. De plus, de cette façon, vous n'obtenez pas cette erreur.

L'exemple ci-dessous montre également que, le troisième thread ne peut pas faire son travail avant le dé principal. Mais cette erreur ne peut pas arriver aussi, tant que vous détachez quelque part dans le code. Le troisième fil dort pendant 8 secondes mais le fil principal mourra dans 5 secondes.

void thread(int n) {std::this_thread::sleep_for (std::chrono::seconds(n));}

int main() {
std::cout << "Start main\n";
std::thread t(thread,1);
std::thread t2(thread,3);
std::thread t3(thread,8);
sleep(5);

t.detach();
t2.detach();
t3.detach();
return 0;}
0
user2908225