Bil*_*ang 3 c++ lifetime c++11 stdthread
#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;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,text变量会在构造函数中正确打印。然而,在long_task()单独线程中运行的函数中,文本被破坏(它在另一台机器上彻底崩溃)。怎么会这样?如果 的析构函数safe_thread在 的析构函数中运行,那么和struct s的生命周期不应该一样长吗?即,当 s 超出范围时,它们都会超出范围?threadtextmain()
raf*_*x07 10
你的问题是在s类中声明成员变量的顺序。
int main()
{
s s;
// here is called dtor of S
}
Run Code Online (Sandbox Code Playgroud)
当析构函数被调用时,数据成员会以其声明的相反顺序被销毁。你有:
safe_thread t; // [2]
std::string text = "for whatever reason, this text will get corrupted"; // [1]
Run Code Online (Sandbox Code Playgroud)
因此,当第一个字符串 [1] 被销毁时,会调用 [2] 线程的析构函数,并且在此调用期间您的程序将加入。但随后它正在访问被破坏的text变量。是UB。
将顺序改为:
std::string text = "for whatever reason, this text will get corrupted";
safe_thread t;
Run Code Online (Sandbox Code Playgroud)
使用这种方法,在加入时t,text变量仍然可见并且不会被删除。
| 归档时间: |
|
| 查看次数: |
137 次 |
| 最近记录: |