1

我有一个程序在启动时创建一个线程(我使用 C++ Boost 库来创建线程)。在主程序中,我已将我的清理功能注册为。

atexit(cleanExit)
// Trap some signals for a clean exit.
signal(SIGQUIT, signalled)
signal(SIGABRT, signalled)
signal(SIGTERM, signalled)
signal(SIGINT, signalled)

static void signalled(int signal)
{
    exit(signal)
}
static void cleanExit(void)
{
     thread->interrupt();
     thread->join();
}

正如您在上面的干净退出过程中看到的那样,我中断了线程,然后在此处(在主进程中)等待,以便线程执行其清理工作。当我调用 thread->interrupt 时,我的线程会被中断,我会执行线程清理工作。到这里一切都很顺利,没有问题。

但是当我在线程中调用清理函数时问题就来了。在清理函数中,我将一些状态发送回服务器,为此我创建了一个实用函数,在这个实用函数中,我正在访问该类的“const static string”成员。问题是当我访问这个 const 静态字符串时,我的应用程序卡住了。我已经用 strace 进行了检查,我得到了一个 Seg Fault。但是当我将这个“const static string”更改为“const string”时,我的清理工作顺利进行。

问题 一旦程序终止,C++“const static”的行为是什么。当 exit 被调用(可以在上面的例子中看到)或对此行为有任何想法时,他们是否放弃了。


更新#1

这是线程处理函数。正如我上面提到的,它是一个 Boost 线程。

try {
    while ( true ) {
        // Do your job here.
        // 1: We can be interrupted.
        boost::this_thread::interruption_point();
    }
}
catch (boost::thread_interrupted const& )
{
    // Before exiting we need to process all request messages in the queue
    completeAllWorkBeforeExiting();
}

当主程序调用 thread->interrupt 时,线程将在 #1 处引发 thread_interrupted 异常,并捕获此异常我正在做我的清理工作。

4

1 回答 1

2

const不影响任何对象被销毁的时间。

static对象的销毁顺序与其创建顺序相反。atexit本质上是用给定的函数创建一个匿名static对象作为它的析构函数。也就是说,static对象析构函数和atexit回调按照与它们的构造/注册相反的顺序发生。

exit从信号处理程序调用是完全不安全的。实际上允许信号处理程序做的所有事情都是设置一个标志,稍后由线程轮询。正如您所提到的,信号处理程序在中断时运行,因此它可能会中断系统调用。malloc它可能会以绕过 的多线程锁的方式中断malloc,因为重入是在同一个线程上,而不是通常发生的不同线程。

所以这是各种不可预测行为的根源。如果没有看到更多,我无法更具体地了解所产生static的效果,但它可能与更改对象的生命周期和/或每个对象实例化一次有关。

于 2013-01-09T08:14:47.270 回答