Otrzymuję błąd C ++ z wątkami:
terminate called without an active exception
Aborted
Oto kod:
#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;
};
Modelowałem swój kod na podstawie tego przykładu: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
Co robię źle i jak naprawić błąd?
c++
multithreading
deadlock
c++11
111111
źródło
źródło
join
wszystkie wątki znajdują się w głównym programie?Odpowiedzi:
Kiedy obiekt wątku wychodzi poza zasięg i jest w stanie łączenia, program jest przerywany. Komitet Standardowy miał dwie inne opcje dla destruktora łączonego wątku. Może się po cichu dołączyć - ale połączenie może nigdy nie powrócić, jeśli wątek utknie. Lub może odłączyć nić (odłączonego wątku nie można łączyć). Jednak odłączone wątki są bardzo trudne, ponieważ mogą przetrwać do końca programu i zepsuć zwolnienie zasobów. Jeśli więc nie chcesz przerywać programu, upewnij się, że dołączasz (lub odłączasz) każdy wątek.
źródło
std::async
? Jak dołączyć / odłączyć dowolny wątek, który może zostać tam utworzony? Wydaje się, że nie wystarczy czekać na wynikową przyszłość, ponieważ mówi, że wątek może „potencjalnie pochodzić z puli wątków”, a funkcja wait () w przyszłości nie oznacza tak naprawdę zakończenia wątku w puli (i to nie i tak nie ma sensu dla rozsądnych pul wątków).std::jthread
wywoła.join()
destruktor (ponieważ wychodzi poza zakres). Które osobiście bardziej mi się podoba, ponieważ lepiej podąża za RAII.Jak odtworzyć ten błąd:
#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; }
Skompiluj i uruchom:
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)
Otrzymujesz ten błąd, ponieważ nie dołączyłeś ani nie odłączyłeś swojego wątku.
Jednym ze sposobów, aby to naprawić, dołącz do wątku w ten sposób:
#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; }
Następnie skompiluj i uruchom:
el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 el@defiant ~/foo4/39_threading $ ./s task1 says: hello
Innym sposobem, aby to naprawić, odłącz go w ten sposób:
#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. }
Skompiluj i uruchom:
el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 el@defiant ~/foo4/39_threading $ ./s task1 says: hello
Przeczytaj o odłączaniu wątków C ++ i dołączaniu do wątków C ++.
źródło
Eric Leschinski i Bartosz Milewski już udzielili odpowiedzi. Tutaj postaram się przedstawić to w bardziej przyjazny dla początkujących sposób.
Po uruchomieniu wątku w zakresie (który sam działa w wątku), należy jawnie upewnić się, że jedna z poniższych sytuacji nastąpi, zanim wątek wyjdzie poza zakres:
Zauważ, że zanim wątek zostanie przyłączony lub odłączony, może być dobrze zakończony. Nadal każda z tych dwóch operacji musi być wykonana jawnie.
źródło
Tak długo, jak twój program umiera, to bez odłączania lub łączenia wątku ten błąd wystąpi. Bez odłączania i łączenia wątku należy po utworzeniu wątku dawać nieskończoną pętlę.
int main(){ std::thread t(thread,1); while(1){} //t.detach(); return 0;}
Ciekawe jest również to, że po spaniu lub zapętleniu nić można odłączyć lub połączyć. Również w ten sposób nie otrzymasz tego błędu.
Poniższy przykład pokazuje również, że trzeci wątek nie może wykonać swojej pracy przed główną śmiercią. Ale ten błąd też nie może się zdarzyć, o ile odłączysz gdzieś w kodzie. Trzeci wątek zostanie uśpiony przez 8 sekund, ale główny umrze za 5 sekund.
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;}
źródło
rok, wątek musi być join (). kiedy główne wyjście
źródło
Najpierw definiujesz wątek. A jeśli nigdy nie wywołasz funkcji join () ani detach () przed wywołaniem destruktora wątków, program przerwie działanie.
Jak poniżej, wywołanie destruktora wątku bez uprzedniego wywoływania join (aby poczekać na jego zakończenie) lub detach jest gwarantowane natychmiastowego wywołania std :: terminate i zakończenia programu.
źródło