C++ terminate вызывается без активного исключения


Я получаю ошибку C++ с потоковой обработкой:

terminate called without an active exception
Aborted

вот код:

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

я смоделировал свой код вокруг этого примера: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

что я делаю неправильно и как исправить ошибку?

3   51   2011-09-12 02:37:04

3 ответа:

когда объект потока выходит из области видимости и находится в соединяемом состоянии, программа завершается. У стандартного комитета было два других варианта деструктора присоединяемого потока. Он может тихо присоединиться - но соединение может никогда не вернуться, если нить застряла. Или он может отсоединить нить (отсоединенная нить не может быть присоединена). Однако отсоединенные потоки очень сложны, так как они могут выжить до конца программы и испортить выпуск ресурсов. Так что если вы не хотите завершите свою программу, убедитесь, что вы присоединяете (или отсоединяете) каждый поток.

как воспроизвести эту ошибку:

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

компиляция и запуск:

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

вы получаете эту ошибку, потому что вы не присоединились или отсоединить поток.

один из способов исправить это, присоединиться к потоку следующим образом:

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

затем скомпилировать и запустить:

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

другой способ исправить это, отсоедините его следующим образом:

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

компиляция и запуск:

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

Читать далее отсоединение потоков C++ и присоединение потоков C++.

Эрик Лещинский и Бартош Милевский уже дали ответ. Здесь я постараюсь представить его в более дружественной для начинающих манере.

Как только поток был запущен в пределах области (которая сама работает в потоке), необходимо явно гарантировать, что одно из следующих событий произойдет до того, как поток выйдет из области:

  • среда выполнения выходит из области, только после того, как этот поток завершает выполнение. Это достигается путем соединения с этой нитью. Обратите внимание на язык, это внешняя область, которая соединяется с этим потоком.
  • среда выполнения оставляет поток для запуска самостоятельно. Таким образом, программа выйдет из области действия, независимо от того, завершил ли этот поток выполнение или нет. Этот поток выполняется и завершается сам по себе. Это достигается путем отсоединения потока. Это может привести к проблемам, например, если поток ссылается на переменные в этой внешней области.

обратите внимание, что к тому времени, когда поток соединяется или отсоединяется, он может быть хорошо закончен проведение. Тем не менее, любая из двух операций должна выполняться явно.