优化器删除指针解引用行

5

我遇到了一个问题,优化器似乎删除了非常必要的代码行。一些背景:我有一个与PCIe驱动程序交互的程序。我有一个整数指针UINT32 *bar_reg;,它指向我正在通信的BAR寄存器的用户空间地址。要写入寄存器,我只需解引用指针。*(bar_reg + OFFSET) = value;

在没有任何优化的情况下,这个方法可以正常工作。但是一旦我打开任何级别的优化,所有解引用指针的行都会被删除。我最终是通过在Visual Studio中逐步执行才发现了这个问题,然而不受平台影响。直到现在我一直在关闭优化器的情况下使用这个程序,但是在Linux中使用我的库代码的某个人想要打开优化器。因此,我想知道为什么会出现这个问题,以及最合理的修复/解决方法是什么。


代码优化后表现不同通常是由于未定义行为。 - Neil Kirk
2个回答

6

使用volatile关键字可以防止对该变量的优化。

例如:

volatile UINT32 *bar_reg;

这里的问题在于编译器假定由于程序未访问内存,因此内存将保持不变,因此它可能会尝试优化对该内存的一些写入操作。

2
您遇到的问题涉及到仿佛规则,它允许优化器以任何方式转换您的代码,只要不影响程序的可观察行为。
因此,如果您只写入变量但从未在程序中实际使用它,则优化器认为没有可观察的行为,并假定可以有效地优化掉写操作。
在您的情况下,数据在程序外被观察到,向编译器和优化器指示的方法是通过volatile限定符,cppreference告诉我们(以下是我的强调):

类型为volatile-qualified的对象,或者是volatile对象的子对象,或者是const-volatile对象的可变子对象。对于优化目的,volatile对象上的每个访问(读取或写入操作、成员函数调用等)都被视为可见的副作用[...]

供参考,《as-if规则》在草案C++标准的第1.9节中有所涉及,该节说:
“相反,符合要求的实现需要模拟(仅)以下所解释的抽象机器的可观察行为。”
“关于‘as-if rule’,volatile也在第1.9节中有涵盖,它说:访问volatile对象严格按照抽象机器的规则进行评估。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接