简体   繁体   English

在 std::thread 中运行时,C++ 成员变量的生命周期是多少?

[英]What is the lifetime of C++ member variables when running in a std::thread?

#include <iostream>
#include <string>
#include <thread>

using namespace std;

struct safe_thread : public thread
{
    using thread::thread;

    safe_thread& operator=(safe_thread&&) = default;

    ~safe_thread()
    {
        if (joinable())
        {
            join();
        }
    }
};

struct s
{
    safe_thread t;
    std::string text = "for whatever reason, this text will get corrupted";

    s() noexcept
    {
        std::cout << text << '\n'; // it works in constructor as expected
        t = safe_thread{ [this]
                         { long_task(); }};
    }

    void long_task()
    {
        for (int i = 0; i < 500; ++i)
        {
            std::cout << text << '\n'; // the text gets corrupted in here
        }
    }
};

int main()
{
    s s;
}

In the code above, the text variable would print correctly in the constructor.在上面的代码中, text变量将在构造函数中正确打印。 However, in the long_task() function running in a separate thread, the text gets corrupted (it outright crashes on another machine).然而,在单独线程中运行的long_task()函数中,文本被破坏(它在另一台机器上彻底崩溃)。 How is that so?怎么会这样? If the destructor of safe_thread would be run in the destructor of struct s , shouldn't the lifetime of thread and text last equally long?如果safe_thread的析构函数在struct s的析构函数中运行,那么threadtext的生命周期不应该一样长吗? Ie they would both go out of scope when s goes out of scope at main() ?即,当 s 在main()超出范围时,它们都会超出范围?

Your problem is in the order of declaration member variables inside s class.你的问题是在s类中声明成员变量的顺序。

int main()
{
    s s;
    // here is called dtor of S
}

When destructor is called data members are destroyed in reverse order of their declarations.当析构函数被调用时,数据成员会以其声明的相反顺序被销毁。 You have:你有:

safe_thread t; // [2]
std::string text = "for whatever reason, this text will get corrupted"; // [1]

so as first string [1] is destroyed, then [2] thread's destructor is invoked and during this invocation your program joins.因此,当第一个字符串 [1] 被销毁时,会调用 [2] 线程的析构函数,并且在此调用期间您的程序将加入。 But then it is accessing destroyed text variable.但随后它正在访问被破坏的text变量。 It is UB.是UB。

Change the order to be:将顺序改为:

std::string text = "for whatever reason, this text will get corrupted";
safe_thread t;

With this approach, while joining t , text variable is still visible and not deleted.使用这种方法,在加入ttext变量仍然可见并且不会被删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM