C ++ завершение вызова без активного исключения - PullRequest
63 голосов
/ 12 сентября 2011

Я получаю ошибку 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

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

Ответы [ 4 ]

88 голосов
/ 03 ноября 2011

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

34 голосов
/ 24 февраля 2014

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

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

Скомпилируйте и запустите:

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)

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

Один из способов исправить это, присоединиться к ветке так:

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

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

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/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.
}

Скомпилируйте и запустите:

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

Читайте об отключении потоков C ++ и присоединении к потокам C ++.

16 голосов
/ 16 мая 2015

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

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

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

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

0 голосов
/ 30 июня 2019

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

int main(){

std::thread t(thread,1);

while(1){}

//t.detach();
return 0;}

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

Приведенный ниже пример также показывает, что третий поток не может выполнить свою работу до основного кубика. Но эта ошибка также не может произойти, пока вы отсоединяетесь где-то в коде. Третий поток спит 8 секунд, но основной умрет через 5 секунд.

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