as-if规则和删除分配

Joh*_*erg 9 c++ as-if c++14

" as-if规则 "使编译器有权优化或重新排序表达式,这些表达式在某些规则下不会对程序的输出和正确性产生影响,例如;

§1.9.5

执行格式良好的程序的一致实现应该产生与具有相同程序和相同输入的抽象机的相应实例的可能执行之一相同的可观察行为.

我上面链接的cppreference url特别提到了易失性对象的值的特殊规则,以及C++ 14下的"新表达式":

New-expression还有as-if规则的另一个例外:即使提供了用户定义的替换并且具有可观察的副作用,编译器也可以删除对可替换分配函数的调用.

我认为这里的"可替换"是所谓的例如

§18.6.1.1.2

可替换:C++程序可以使用此函数签名定义一个函数,该函数取代了C++标准库定义的默认版本.

以下是否mem可以根据as-if规则删除或重新排序?

  {
  ... some conformant code // upper block of code

  auto mem = std::make_unique<std::array<double, 5000000>>();

  ... more conformant code, not using mem // lower block of code
  }
Run Code Online (Sandbox Code Playgroud)

有没有办法确保它不被删除,并保持在代码的上下块之间?mem我想到了一个放置良好的volatile(或/或volatile std :: array或auto的左侧),但由于没有读取,我认为即使这样也无法在as-if规则下提供帮助.

边注; 我无法让visual studio 2015进行优化mem和分配.

澄清:观察这种情况的方法是对OS的分配调用来自两个块的任何i/o.这一点是针对测试用例和/或尝试在新位置分配对象.

Yak*_*ont 4

是的; 不,不在 C++ 中。

C++的抽象机根本不讲系统分配调用。只有影响抽象机行为的此类调用的副作用才由 C++ 修复,即使如此,编译器也可以自由地执行其他操作,只要它会导致抽象机部分产生相同的可观察行为。抽象机中的程序。

在抽象机中,auto mem = std::make_unique<std::array<double, 5000000>>();创建一个变量memdouble如果使用它,您可以访问打包到数组中的大量s。抽象机可以自由地抛出异常,或者为您提供大量的doubles;两者都可以。

new请注意,它是一个合法的 C++ 编译器,通过无条件throw分配失败(或返回nullptr无抛出版本)来替换所有分配,但这将是一个较差的实现质量。

在分配它的情况下,C++ 标准并没有真正说明它来自哪里。例如,编译器可以自由使用静态数组,并使调用成为delete无操作(注意,它可能必须证明它捕获了调用delete缓冲区的所有方法)。

接下来,如果您有一个静态数组,如果没有人读取或写入它(并且无法观察到构造),则编译器可以随意消除它。


话虽如此,上述大部分内容都依赖于编译器了解正在发生的情况。

所以一个办法就是让编译器无法知道。让您的代码加载一个 DLL,然后unique_ptr在您希望了解其状态的位置传递一个指向该 DLL 的指针。

由于编译器无法优化运行时 DLL 调用,因此变量的状态基本上必须是您期望的状态。

遗憾的是,没有像 C++ 那样动态加载代码的标准方法,因此您必须依赖当前的系统。

所述DLL可以单独写成noop;或者,您甚至可以检查某些外部状态,并根据外部状态有条件地加载数据并将其传递到 DLL。只要编译器无法证明会发生所述外部状态,它就无法围绕进行的调用进行优化。然后,永远不要设置该外部状态。

在块的顶部声明变量。在未初始化时将指向它的指针传递给 fake-external-DLL。在初始化之前重复,然后在初始化之后重复。最后,在销毁它之前在块的末尾执行此操作.reset(),然后再执行一次。

  • @BenVoigt 我看到两个“?”。我现在已经按顺序回答了。 (2认同)