【发布时间】:2017-03-17 03:37:15
【问题描述】:
我的一位同事声称,一旦对象的析构函数调用开始,线程对对象成员的所有访问(即对象本身的成员)都是 UB。
这意味着如果线程正在访问对象的任何其他成员,则在对象的析构函数期间调用 std::thread::join 是 UB。
我在“对象生命周期”下简要查看了最新的标准草案,但找不到能给我确定答案的内容。
以下代码(on wandbox) 是否引入了未定义的行为?标准中阐明这种交互的部分是什么?
struct A
{
atomic<bool> x{true};
thread t;
// Capturing 'this' is part of the issue.
// The idea is that accessing 'this->x' becomes invalid as soon as '~A()' is entered.
// vvvv
A() : t([this]
{
while(x)
{
this_thread::sleep_for(chrono::milliseconds(100));
}
})
{
}
~A()
{
x = false;
t.join();
}
};
int main()
{
A a;
}
【问题讨论】:
-
没有任何意义。他的意思是在析构函数中删除原始成员指针也是 UB,因为这是在主线程上发生的,或者他的意思是 2 个线程执行析构函数,这意味着竞争条件和不正确的代码。你最好问问他信仰的来源:)
-
"[class.cdtor]/1 对于具有非平凡析构函数的对象,在之后引用对象的任何非静态成员或基类析构函数完成执行会导致未定义的行为。”强调我的。这似乎意味着在析构函数完成执行之前访问成员是可以的。
-
想一想:你通常在析构函数中所做的一切都取决于那些仍然活着的成员。析构函数没有任何可以处理的参数,它唯一有的是
this所以this->更好地引用可用的对象。
标签: c++ multithreading c++11 language-lawyer undefined-behavior