c++ - 假设规则和移除分配

标签 c++ c++14 as-if

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

§1.9.5

A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input.

我在上面链接的 cppreference url 特别提到了 C++14 下 volatile 对象的值以及“新表达式”的特殊规则:

New-expression has another exception from the as-if rule: the compiler may remove calls to the replaceable allocation functions even if a user-defined replacement is provided and has observable side-effects.

我假设这里的“可替换”就是在

中讨论的例子

§18.6.1.1.2

Replaceable: a C++ program may define a function with this function signature that displaces the default version defined by the C++ standard library.

根据 as-if 规则,下面的 mem 可以被删除或重新排序是否正确?

  {
  ... 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,我认为即使这样在 下也无济于事好像规则。

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

澄清:观察的方法是,对操作系统的分配调用来自两个 block 的任何 i/o 之间。这一点是针对测试用例和/或尝试让对象分配到新位置。

最佳答案

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

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

在抽象机中,auto mem = std::make_unique<std::array<double, 5000000>>();创建一个变量 mem .如果使用它,您可以访问大量 double s 打包成一个数组。抽象机可以随意抛出异常,或者为你提供那么大量double ;两者都可以。

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

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

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


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

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

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

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

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

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

关于c++ - 假设规则和移除分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34907922/

相关文章:

c++ - 如何从 boost::container::vector<std::string>::iterator 访问索引和对象?

c++ - 为模板类重载比较运算符

c++ - 在类中的函数外部归档 vector

c++ - 具有私有(private)构造函数的 unordered_map 值类型

c++ - 如何保护进程免受 writeprocessmemory 的影响?

c++ - lambda 的生命周期在 const lambda 中捕获引用

c++ - 将包含 CONST char 数组 [N] 成员的结构的聚合初始化转换为构造函数

c++ - C++ 标准中 "as if"规则的声明或基础在哪里?

c++ - C++中复制省略背后的基本原理是什么?