9

考虑这段代码,其中xy是整数:

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,则不应写入任何变量。
但是如果允许转换呢?

4

2 回答 2

7

y与我在不正确的评论中所写的不同,如果线程之间可能共享并且编译器无法证明原始代码中存在任何现有的 UB,则实际上不允许这种转换。

该标准明确规定:

该标准通常排除了将分配引入抽象机不会修改的潜在共享内存位置的编译器转换,因为在抽象机执行不具有的情况下,这样的分配可能会覆盖不同线程的另一个分配遇到了数据竞争。

[intro.multithread] (1.10/22) 在 N3337 中,(1.10/25) 在 N4141 中。

因此,如果x始终为 0,则原始代码将是无竞争的,而转换后的代码则不会。因此,转换是不合法的。

于 2017-08-25T16:17:09.263 回答
0

如果是这样,那么您将无法排除对可从全局变量或其他变量访问的任何对象的访问。编译器甚至可以在进行间接调用时试探性地调用从未调用过的函数,然后通过恢复原始值“取消”它们的效果。

沿着这条优化-悲观路径,它可以提前除以零,然后如果除数为零,则“忽略”结果,即使这是一个陷阱并且程序已停止。

这显然是荒谬的,无论标准是否应该如此,都必须拒绝。

于 2019-07-10T16:55:35.500 回答