gpt4 book ai didi

C++:一个对象既可以存储也可以不存储吗?

转载 作者:行者123 更新时间:2023-11-27 23:55:16 24 4
gpt4 key购买 nike

我一直在争论关于多线程环境中局部变量的极端情况。

问题是关于这样形成的程序:

std::mutex mut;

int main()
{
std::size_t i = 0;
doSomethingWhichMaySpawnAThreadAndUseTheMutex();
mut.lock();
i += 1; // can this be reordered?
mut.unlock();
return i;
}

问题围绕着 i += 1 是否可以重新排序以发生在互斥锁之上。

明显的部分是 mut.lock() happens-before i += 1,所以如果任何其他线程可能能够为了观察 i 的值,编译器必须不增加它。从 C++ 规范的 3.9.2.3 开始,“如果类型 T 的对象位于地址 A,则称其值为地址 A 的类型 cv T* 的指针指向该对象,无论该值是如何获得的。""这意味着如果我使用任何方法获取指向 i 的指针,我可以期望看到正确的值。

但是,规范确实声明编译器可以使用“as-if”规则不为对象提供内存地址(第 1.8.6 节脚注 4)。例如,i 可以存储在没有内存地址的寄存器中。在这种情况下,将没有可指向的内存地址,因此编译器可以证明没有其他线程可以访问 i

我感兴趣的问题是,如果编译器不执行这种“as-if”优化,并且确实存储了对象怎么办。是否允许编译器存储 i,但重新排序就好像 i 没有实际存储一样?从实现的角度来看,这意味着 i 可能存储在堆栈中,因此可能有一个指针指向它,但编译器假设没有人可以看到 i ,然后重新排序?

最佳答案

只要在没有这些优化的情况下合法地获得(“as-if”)程序执行的可观察结果,就允许编译器执行优化。[1] 所以这个问题使用“as-if”以一种误导的方式,如果实际上不是在问一个倒退的问题:

Is the compiler permitted to store i, but do reordering as-if i was not actually stored?

这询问是否允许编译器做一些事情,只要程序执行的结果可以通过优化获得。那不是要问的问题。该问题应使用未优化的行为作为引用。所以更像是:“是否允许编译器对语句重新排序?” 答案是肯定的,只要可观察的结果不变。这个特定函数的外部没有被告知如何访问 i ,因此应该允许编译器在它的周围使用之间的任何地方实现增量(特别是:它的定义和 return 语句)。

也就是说,我希望编译器在这种情况下不会给出 i。内存地址,也不将其视为寄存器变量。我希望编译器将其视为常量,有效地将您的函数更改为:

int main()
{
doSomethingWhichMaySpawnAThreadAndUseTheMutex();
mut.lock();
mut.unlock();
return 1;
}

只要您无法检测到它已经完成(除了直接检查机器代码),就允许这样做。

注意:
[1] 使用“本来可以”是承认 C++ 规范的某些部分使用了“未指定”一词。这些部分允许编译器做出选择(在处理非健壮代码时)可以改变可观察到的行为。也就是说,可以有一组允许的行为,而不是单个允许的行为。只要结果保留在这个集合中,就允许优化。

关于C++:一个对象既可以存储也可以不存储吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50729420/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com