繁体   English   中英

as-if规则和删除分配

[英]as-if rule and removal of allocation

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
  }

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

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

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

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

C ++的抽象机器根本不讨论系统分配调用。 只有影响抽象机器行为的这种调用的副作用才能被C ++修复,即使这样,编译器也可以自由地做其他的事情,只要它能产生相同的可观察行为。程序在抽象机器中。

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

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

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

接下来,如果你有一个静态数组,如果没有人读或写(并且无法观察到结构),编译器可以自由地消除它。


话虽如此,上面的大部分都依赖于编译器知道发生了什么。

因此,一种方法是让编译器无法知道。 让您的代码加载DLL,然后在您希望其状态被知道的点处将指针传递给该DLL的unique_ptr

因为编译器无法优化运行时DLL调用,所以变量的状态必须基本上与您期望的一样。

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

所述DLL可以单独写成noop; 或者,甚至,您可以检查一些外部状态,并根据外部状态有条件地加载并将数据传递给DLL。 只要编译器不能证明说会发生外部状态,它不能左右没有进行的调用进行优化。 然后,永远不要设置外部状态。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM