use*_*522 5 c++ multithreading lifetime language-lawyer
如果添加任一注释行,以下程序是否具有 UB?
#include<atomic>
#include<iostream>
#include<thread>
std::atomic<bool> a = false;
struct T {
int i;
void reset() { i = 0; }
~T() {
while(!a);
//reset();
a = false;
while(!a);
}
};
int main() {
std::thread x;
{
const T t{42};
x = std::thread([&t]{
std::cout << t.i << "\n";
a = true;
while(a);
//const_cast<T&>(t).reset();
//const_cast<int&>(t.i) = 0;
std::cout << t.i << "\n";
a = true;
});
}
x.join();
}
Run Code Online (Sandbox Code Playgroud)
GCC 打印42后跟0,而 Clang 打印42两次:https://godbolt.org/z/j544rq3cx
如果t我不直接在线程中使用,而是捕获对t.i(在析构函数调用开始之前同步)的引用并通过该引用进行读取和写入,该怎么办?在这种情况下,成员访问不必t在生命周期之外发生。有趣的是,我无法使用42这样的构造让 Clang 打印两次。
直觉上我已经说过 UB 了,因为i它是在生命周期之外访问的t(在调用析构函数时结束),但是此时t处于“被破坏”状态并且适用不同的规则,并且我没有找到任何明确说明 UB 的内容。
另外,为了避免混淆,我认为conston不t应该对其是否为 UB 产生任何影响。然而,这const表明这对编译器优化有影响,正如 Clang 处理它的方式所示。除了在构造和销毁期间之外const,不能修改自动存储持续时间对象,也不能替换该对象,因此编译器通常可以假设i不会更改其值,即使对t转义到未知函数的引用也是如此。
| 归档时间: |
|
| 查看次数: |
149 次 |
| 最近记录: |