2011-09-11 9 views
39

estoy recibiendo un error de C++ con rosca:C++ terminar el arrendamiento llama sin excepción activa

terminate called without an active exception 
Aborted 

Aquí está el 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; 
}; 

modelé mi código en torno a este ejemplo: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

¿Qué estoy haciendo mal y cómo soluciono el error?

+3

¿Estás 'join'ing todos tus hilos en tu programa principal? –

+0

Muéstranos el resto del código. – Matt

+1

@Kerrek ah ha solucionado el problema, no tengo idea de por qué, aunque estoy seguro de que el hilo principal no terminaba antes de que los trabajadores terminaran. También mis alogoritos de bloqueo se ven bien? – 111111

Respuesta

63

Cuando un objeto de subproceso queda fuera de alcance y se puede unir, el programa finaliza. El Comité Estándar tenía otras dos opciones para el destructor de un hilo que se puede unir. Podría unirse de forma silenciosa, pero unirse podría no volver nunca si el hilo está atascado. O podría separar el hilo (un hilo separado no se puede unir). Sin embargo, los hilos separados son muy difíciles, ya que podrían sobrevivir hasta el final del programa y arruinar la liberación de recursos. Por lo tanto, si no desea finalizar su programa, asegúrese de unirse (o desconectar) cada hilo.

+0

"Cuando un objeto de subproceso queda fuera de alcance y se puede unir, el programa finaliza" ¿Podría proporcionar un ejemplo reproducible, simple y muerto de esto? El ejemplo en OP es un poco complicado. –

+1

Y esa afirmación parece contradictoria a esta respuesta: http://stackoverflow.com/a/3970921/148668 –

+4

@mangledorf: Observe que están hablando de otra manera :: boost :: thread y estoy hablando de std :: thread. Estos dos tienen diferentes comportamientos de destrucción. Esta fue una decisión consciente por parte del Comité. –

22

cómo reproducir ese error:

#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 y ejecute:

[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) 

Usted consigue que el error porque no se inscribió o desconectar el hilo.

Una forma de solucionarlo, se unen al hilo de la siguiente manera:

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

A continuación, compilar y ejecutar:

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

La otra forma de solucionarlo, separar de esta manera:

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

Compilar y ejecutar:

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

Lectura sobre cómo desacoplar los hilos C++ y unir los hilos C++.

+0

en este contexto, el uso de usleep() tiene sentido solo si el hilo se suelta y el mango se destruye (saliéndose del alcance). SO he editado tu código para reflejar esto. – Nawaz

4

Eric Leschinski y Bartosz Milewski ya dieron la respuesta. Aquí, trataré de presentarlo de una manera más amigable para principiantes.

Una vez que un mensaje ha sido iniciado dentro de un ámbito (que a su vez se ejecuta en un hilo), uno debe asegurarse de forma explícita una de las siguientes ocurre antes de que el hilo se sale del ámbito:

  • El tiempo de ejecución sale de la alcance, solo después de que el hilo termine de ejecutarse. Esto se logra al unirse con ese hilo. Tenga en cuenta el idioma, es el alcance externo que se une con ese hilo.
  • El tiempo de ejecución deja que el hilo se ejecute solo. Entonces, el programa saldrá del alcance, ya sea que este subproceso termine de ejecutarse o no. Este hilo se ejecuta y sale solo. Esto se logra separando el hilo. Esto podría generar problemas, por ejemplo, si el hilo se refiere a variables en ese ámbito externo.

Nota: para cuando el hilo se une o se separa, puede que se haya terminado de ejecutar. Aún así, cualquiera de las dos operaciones debe realizarse de forma explícita.

Cuestiones relacionadas