想象一下这段代码:
线程 1(函数):
#include <cstdio>
#include <thread>
struct t_arr
{
int _[2];
} *volatile pvar = nullptr;
volatile bool var1;
void func(bool x, t_arr ar)
{
pvar = &ar;
(x ? ar._[0] : ar._[1]) = 90; //this whole statement optimized out
while(!var1);
}
typeof(func) *pFunc = func;
当我编译它时(确切的命令是 g++ -O3 -std=gnu++1y snippet.cpp -pthread
)生成的函数体 func
丢失了其中一个 ar
成员被赋予值 90 的分支。
这是允许的优化吗?
如果此时有另一个线程在等待pvar
被赋值怎么办:
线程2(func2):
void func2()
{
while(!pvar); //wait until 'pvar' is assigned
printf("%d %d\n", pvar->_[0], pvar->_[1]); //print it members
var1 = true; //continue 'func'
}
创建上述情况的示例代码:
int main () {
using namespace std;
thread newthread(func2);
pFunc(true, {2, 9});
newthread.join();
return 0;
}
将上述所有片段相继复制,创建一个源文件 (snippet.cpp
)。
如果不是针对每个单独的代码段 - 谈论意图很明显的整个程序。
截图的输出:
2 9
编辑:已修复 - 忘记加入。
最佳答案
关于优化。通过未标记为volatile
的变量ar
进行赋值,指针pvar
是volatile。
因此,由于不再使用该变量(就编译器而言),因此将这些赋值作为删除的候选对象。
通过 volatile 指针进行赋值会禁止编译器优化它们。
(x ? pvar->_[0] : pvar->_[1]) = 90;
请参阅此处的代码示例;代码尚未优化,https://goo.gl/lKQcac .
注意;数据竞争还有更多问题需要适当的同步。
关于c++ - 另一个线程是否可以通过其地址访问本地函数\此优化是否有效\我是否遗漏了一些重要的东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36016883/