考虑这段代码,其中x
和y
是整数:
if (x)
y = 42;
是否允许以下编译器转换?
int tmp = y;
y = 42;
if (!x)
y = tmp;
上下文:
这是来自Bjarne Stroustrup的常见问题:
// start with x==0 and y==0
if (x) y = 1; // Thread 1
if (y) x = 1; // Thread 2
常见问题解答说这是数据竞争免费;如果x
和y
均为0,则不应写入任何变量
但如果允许转换怎么办呢?
答案 0 :(得分:6)
与我在错误的注释中写的不同,如果y
可能在线程之间共享并且编译器无法证明原始代码中的任何现有UB,则实际上不允许进行此转换。
该标准明确指出:
N3337中的[intro.multithread](1.10 / 22),N4141中的(1.10 / 25)。编译器转换,将分配引入可能共享的内存位置 本标准通常排除抽象机器不会修改,因为这样 在抽象机器的情况下,赋值可能会覆盖另一个线程的另一个赋值 执行不会遇到数据竞争。
因此,如果x
始终为0,则原始代码将无竞赛,而转换后的代码将无法进行竞争。因此,转型是不合法的。
答案 1 :(得分:0)
如果是,那么您将无法从全局变量或其他变量中排除对任何可访问对象的访问。每当进行间接调用时,编译器甚至可以临时调用从未调用过的函数,然后通过恢复原始值来“取消”它们的作用。
沿着这条最优化路径,它可以预先除以零,然后如果除数为零,则“忽略”结果,即使那是一个陷阱并且程序已停止。
这显然是荒谬的,无论标准是否应规定,都必须拒绝。