Estou recebendo um erro C ++ com threading:
terminate called without an active exception
Aborted
Aqui está o código:
#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;
};
Eu modelei meu código em torno deste exemplo: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
O que estou fazendo de errado e como corrijo o erro?
c++
multithreading
deadlock
c++11
111111
fonte
fonte
join
usando todos os tópicos do seu programa principal?Respostas:
Quando um objeto de thread sai do escopo e está em estado de junção, o programa é encerrado. O Comitê Padrão tinha duas outras opções para o destruidor de um thread unificável. Ele poderia entrar silenciosamente - mas o join pode nunca retornar se o thread estiver travado. Ou pode desanexar o encadeamento (um encadeamento desanexado não é juntável). No entanto, threads desanexados são muito complicados, pois podem sobreviver até o final do programa e atrapalhar a liberação de recursos. Portanto, se você não quiser encerrar seu programa, certifique-se de juntar (ou desanexar) todos os tópicos.
fonte
std::async
? Como você une / desanexa qualquer tópico que possa ser criado lá? Não parece que esperar pelo futuro resultante seria o suficiente, porque isso diz que o thread poderia "ser potencialmente de um pool de threads", e wait () do futuro não implica realmente encerrar um thread em um pool (e isso não não faz sentido para pools de threads sãos).std::jthread
irá chamar.join()
o destruidor (já que sai do escopo). O que eu pessoalmente gosto mais porque segue melhor o RAII.Como reproduzir esse erro:
#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; }
Compile e execute:
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)
Você obtém esse erro porque não ingressou ou desanexou seu tópico.
Uma maneira de corrigir isso é entrar no tópico desta forma:
#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; }
Em seguida, compile e execute:
el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 el@defiant ~/foo4/39_threading $ ./s task1 says: hello
A outra forma de consertar é desanexar assim:
#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. }
Compile e execute:
el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 el@defiant ~/foo4/39_threading $ ./s task1 says: hello
Leia sobre como desanexar threads C ++ e unir threads C ++.
fonte
Eric Leschinski e Bartosz Milewski já deram a resposta. Aqui, tentarei apresentá-lo de uma maneira mais amigável para iniciantes.
Depois que um thread foi iniciado dentro de um escopo (que por si só está sendo executado em um thread), deve-se garantir explicitamente que uma das seguintes opções aconteça antes que o thread saia do escopo:
Observe que, no momento em que o encadeamento é unido ou desanexado, sua execução pode estar bem concluída. Ainda assim, qualquer uma das duas operações deve ser executada explicitamente.
fonte
Enquanto seu programa morrer, sem separar ou juntar o thread, este erro ocorrerá. Sem separar e unir o fio, você deve dar um loop infinito depois de criar o fio.
int main(){ std::thread t(thread,1); while(1){} //t.detach(); return 0;}
Também é interessante que, depois de dormir ou fazer um loop, o fio pode ser separado ou unido. Também desta forma não obtém este erro.
O exemplo abaixo também mostra que o terceiro thread não pode fazer seu trabalho antes do dado principal. Mas esse erro também não pode acontecer, desde que você desanexe em algum lugar do código. O terceiro thread dorme por 8 segundos, mas o principal morrerá em 5 segundos.
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;}
fonte
ano, o tópico deve ser join (). quando a saída principal
fonte
Primeiro você define um tópico. E se você nunca chamar join () ou detach () antes de chamar o destruidor de thread, o programa será abortado.
Como segue, chamar um destruidor de thread sem primeiro chamar join (para esperar que ele termine) ou desanexar é garantido para chamar imediatamente std :: terminate e terminar o programa.
fonte