在没有活动异常的情况下调用C++ terminate

bt1cpqcv  于 2022-12-05  发布在  其他
关注(0)|答案(6)|浏览(152)

我遇到一个线程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
我做错了什么?如何修复错误?

83qze16e

83qze16e1#

当线程对象超出作用域并且处于可联接状态时,程序终止。标准委员会对于可联接线程的析构函数有另外两种选择。它可以安静地联接--但是如果线程被阻塞,联接可能永远不会返回。或者它可以分离线程(分离的线程是不可连接的)。然而,分离的线程非常棘手,因为它们可能会一直存在到程序结束,并扰乱资源的释放。因此,如果你不想终止程序,请确保加入(或分离)每个线程。

xam8gpfp

xam8gpfp2#

如何重现该错误:

#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线程的内容。

aurhwmvo

aurhwmvo3#

Eric Leschinski和Bartosz Milewski已经给出了答案。在这里,我将尝试以一种对初学者更友好的方式呈现它。
一旦线程在作用域(它本身在线程上运行)内启动,必须显式确保在线程离开作用域之前发生以下情况之一:

  • 只有在该线程完成执行之后,运行库才退出作用域。这是通过与该线程联接来实现的。注意语言,它是与该线程联接的外部作用域。
  • 运行库让线程自己运行。因此,无论此线程是否完成执行,程序都将退出作用域。此线程自己执行并退出。这是通过分离线程实现的。这可能会导致问题,例如,如果线程引用该外部作用域中的变量。

注意,当线程被加入或分离时,它可能已经很好地完成了执行。但是这两个操作中的任何一个都必须显式地执行。

628mspwn

628mspwn4#

首先你定义一个线程,如果你在调用线程析构函数之前没有调用join()或detach(),程序就会中止。
如下所示,在没有首先调用join(等待它完成)或detach的情况下调用线程析构函数,可以保证立即调用std::terminate并结束程序。
在析构函数中隐式分离或联接joinable()线程可能导致难以调试正确性(对于分离)或性能(对于联接)错误,这些错误只有在引发异常时才会遇到。因此,程序员必须确保在线程仍然可联接时从不执行析构函数。

mfuanj7w

mfuanj7w5#

只要你的程序死了,那么没有分离或加入线程,这个错误就会发生。没有分离和加入线程,你应该在创建线程后给予死循环。

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

ruarlubt6#

是的,线程必须是join()。当main退出时

相关问题