[英]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
的析构函数中运行,那么thread
和text
的生命周期不应该一样长吗? 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.使用这种方法,在加入
t
, text
变量仍然可见并且不会被删除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.