std::thread - "terminate called without an active exception" ,不想"加入"它

std::thread - "terminate called without an active exception", don't want to 'join' it

本文关键字:exception 不想 加入 active without thread terminate called std an      更新时间:2023-10-16

根据这个问题,我使用线程在用户输入时终止函数。我的代码看起来像这样:

bool stopper = false;
thread stopThread(userStop, &stopper);      // start thread looking for user input
for(int i = 0; i < 1000; i++) {
    if(stopper) { break; }                  // break if desired
    // Do stuff
}
return 0;

,

userStop(bool *st) {
    char chChar = getchar();
    if(chChar == 'n') {
        *st = true;
    }
}

当我运行这个时,我得到错误terminate called without an active exception。基于这些问题:线程终止调用时没有活动异常,c++终止调用时没有活动异常;这看起来好像是因为我没有再"加入"线程。

问题是,我不想"加入"线程——因为这样用户将需要userStop()终止提供输入,但我只希望用户在for循环被打破时提供输入(这是不必要的)。

谢谢!

您遇到的麻烦是stopThread超出堆栈范围的结果。c++标准对此有如下说明:

30.3.1.3线程析构函数[thread.thread.destr]

~线程();

如果joinable()则terminate(),否则无效。[注:任选。在析构函数中隐式地分离或连接joinable()线程可能导致难以调试正确性(对于分离)或性能(连接)bug只在出现异常时遇到提高。因此,程序员必须确保析构函数永远不会在线程仍然可连接时执行。- 结束说明]

这意味着在没有首先调用join()detach()之前,您不应该让线程超出作用域。

你描述它的方式,你希望线程在没有加入的情况下离开作用域,这样它就会在你的应用程序运行时继续运行。这需要调用detach()。从这里,我只能提供一点智慧……

  • 该线程现在完全负责自己的生命周期。如果它没有自己返回,它将永远运行(直到进程终止)。

  • 您正在获得用户输入,可能来自cingetch()。如果它们是从多个线程访问的,那么您就不能保证它们的库实现中没有竞争条件。小心翼翼。

在您的标准输入线程中,您将希望从输入中异步读取。并在要求停止阅读和新输入时唤醒。

不连接就终止线程是不合理的。所以你需要能够做的是说"你的线程,马上完成",然后能够期望连接将迅速完成。在某些情况下,这甚至可以通过两步握手("你的线程,完成",然后是"好了好了,我设法清理了,现在加入我")。

请注意,到1000的循环看起来非常荒谬:用户输入超时通常应该基于实际时间的流逝,或者其他一些使用户输入无效的事件的发生。

终止线程是一个坏主意——您应该让线程优雅地退出。如果确实终止了线程,最终会导致getch()函数中的代码意外结束。如果该代码处于管理数据结构、分配或释放内存或执行其他必须执行直至完成的工作的中间,该怎么办?您最终会使某些东西处于无效状态,并且当执行该无效状态时,您最终会崩溃。