C++ terminate called without an active exception


Estoy recibiendo un error de C++ con threading:

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 alrededor de 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?

Author: Eric Leschinski, 2011-09-12

3 answers

Cuando un objeto thread sale del ámbito y está en estado joinable, el programa termina. El Comité Estándar tenía otras dos opciones para el destructor de un hilo ensamblable. Podría unirse en silencio join pero unirse nunca podría regresar 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 estropear la liberación de recursos. Así que si no quieres termina tu programa, asegúrate de unir (o separar) cada hilo.

 70
Author: Bartosz Milewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-24 02:42:31

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

Compilar y ejecutar:

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)

Obtienes ese error porque no uniste ni separaste tu hilo.

Una forma de arreglarlo, une el hilo de esta 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;
}

Luego compila y ejecuta:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

La otra forma de arreglarlo, separarlo así:

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

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

Lea sobre cómo separar subprocesos de C++ y unir subprocesos de C++.

 30
Author: Eric Leschinski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-03 11:50:48

Eric Leschinski y Bartosz Milewski ya han dado la respuesta. Aquí, voy a tratar de presentarlo de una manera más amigable para principiantes.

Una vez que se ha iniciado un subproceso dentro de un ámbito (que a su vez se está ejecutando en un subproceso), uno debe asegurarse explícitamente de que ocurre una de las siguientes cosas antes de que el subproceso salga del ámbito:

  • El tiempo de ejecución sale del ámbito, solo después de que ese subproceso termine de ejecutarse. Esto se logra uniendo 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 por sí solo. Por lo tanto, el programa saldrá del ámbito, ya sea que este hilo haya terminado de ejecutarse o no. Este hilo se ejecuta y sale por sí mismo. Esto se logra separando el hilo. Esto podría dar lugar a problemas, por ejemplo, si el hilo se refiere a variables en ese ámbito externo.

Nota, en el momento en que el hilo se une o se separa, puede haber terminado de ejecutarse. Todavía cualquiera de los dos las operaciones deben realizarse explícitamente.

 8
Author: haripkannan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-16 12:14:36