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?
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.
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++.
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:
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.
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;}