2011-09-11 36 views
39

sto ottenendo un errore di C++ con filettatura:C++ Termina chiamata, senza eccezione attiva

terminate called without an active exception 
Aborted 

Ecco il codice:

#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; 
}; 

ho modellato il mio codice in giro per questo esempio: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

Cosa sto facendo male e come posso correggere l'errore?

+3

Stai partecipando a tutti i tuoi thread nel programma principale? –

+0

Mostraci il resto del codice. – Matt

+1

@Kerrek ah ah questo ha risolto il problema, non ho idea del perché, sebbene sia certo, il filo conduttore non è terminato prima della fine dei lavoratori. Anche i miei alogorithms di blocco sembrano giusti? – 111111

risposta

63

Quando un oggetto thread esce dall'ambito ed è in stato joinable, il programma viene terminato. Il comitato standard aveva altre due opzioni per il distruttore di un thread collegabile. Potrebbe tranquillamente unirsi - ma join potrebbe non tornare mai se il thread è bloccato. Oppure potrebbe staccare il thread (un thread distaccato non è univoco). Tuttavia, i thread distaccati sono molto difficili, dal momento che potrebbero sopravvivere fino alla fine del programma e rovinare il rilascio di risorse. Quindi se non vuoi terminare il tuo programma, assicurati di unire (o staccare) ogni thread.

+0

"Quando un oggetto thread esce dallo scope ed è in uno stato joinable, il programma viene terminato" Potresti fornire un esempio semplice e riproducibile di questo? L'esempio nell'OP è un po 'complicato. –

+1

E questa affermazione sembra contraddittoria a questa risposta: http://stackoverflow.com/a/3970921/148668 –

+4

@mangledorf: Si noti che stanno parlando di aobut boost :: thread e sto parlando di std :: thread. Questi due hanno diversi comportamenti distruttivi. Questa è stata una decisione consapevole da parte del Comitato. –

22

come riprodurre questo errore:

#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; 
} 

Compilare ed eseguire:

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

Si ottiene questo errore perché non hai aderire o staccare il tuo thread.

Un modo per risolvere il problema, unire il filo in questo modo:

#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; 
} 

Poi compilare ed eseguire:

[email protected] ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 
[email protected] ~/foo4/39_threading $ ./s 
task1 says: hello 

L'altro modo per risolvere il problema, rimuovere in questo modo:

#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. 
} 

Compilare ed eseguire:

[email protected] ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11 
[email protected] ~/foo4/39_threading $ ./s 
task1 says: hello 

Leggere fino a staccare i thread C++ e unire i thread C++.

+0

in questo contesto, l'uso di usleep() ha senso solo se il thread è staccato e l'handle è stato distrutto (uscendo dall'ambito). Così ho modificato il tuo codice per riflettere questo. – Nawaz

4

Eric Leschinski e Bartosz Milewski hanno già dato la risposta. Qui, proverò a presentarlo in un modo più amichevole per i principianti.

volta un thread è stato iniziato entro un ambito (che a sua volta è in esecuzione su un thread), si deve garantire esplicitamente una delle seguenti avviene prima che il filo passa nell'ambito:

  • Il runtime chiude la ambito, solo dopo che il thread termina l'esecuzione. Ciò si ottiene aderendo a quel thread. Nota la lingua, è lo scope esterno che si unisce a quel thread.
  • Il runtime lascia il thread da eseguire autonomamente. Quindi, il programma uscirà dall'ambito, indipendentemente dal fatto che questo thread abbia finito o meno l'esecuzione. Questo thread esegue ed esce da solo. Questo si ottiene staccando il filo. Ciò potrebbe causare problemi, ad esempio, se il thread fa riferimento a variabili in tale ambito esterno.

Nota: quando il thread viene unito o rimosso, è possibile che l'esecuzione sia completata correttamente. Ancora una delle due operazioni deve essere eseguita in modo esplicito.

Problemi correlati