如果它调用共享库,C ++中的无限循环仍然是未定义的行为吗?

时间:2016-12-25 11:26:41

标签: c++ infinite-loop undefined-behavior

据说无限循环for(;;);是未定义的行为。

来自http://en.cppreference.com/w/cpp/language/memory_model

  

在一个有效的C ++程序中,每个线程最终会执行其中一个   以下内容:

     
      
  • 终止
  •   
  • 调用I / O库函数
  •   
  • 读取或修改易失性对象
  •   
  • 执行原子操作或同步操作
  •   
     

没有执行任何操作,任何执行线程都不能永久执行   这些可观察的行为。

     

请注意,这意味着程序具有无限递归或无穷无尽   循环(无论是作为for语句实现还是通过循环goto或   否则)有不确定的行为。

但是如果它在共享库中调用一个函数呢?

for(;;) sofunc();

该函数可以执行任何类型的阻塞I / O或抛出异常。

在这种情况下,编译器是否认为循环有一些可观察的行为?

1 个答案:

答案 0 :(得分:3)

有许多地方标准的语言使编制者的自由超出了有用优化所需的自由,但这会为编制者提供将窗口中最小惊讶原则抛到窗外的方法。关于无限循环的规则的编写方式符合该类别。

有关无限循环的规则将促进的大多数优化都将通过语言来启用,该语言指定执行一段代码所需的时间,即使无限,也不被认为是是编译器需要保留的副作用。这样的规则将允许编译器省略任何没有任何直接副作用的循环迭代,并且不会修改在别处使用的值。

然而,标准不仅限于此。鉴于代码:

int foo(void)
{
  int x=0;
  do
  {
    x=functionWithNoSideEffects(x);
  } while(x != 23 && x != 42);
  return x;
}

一个可以显示functionWithNoSideEffects永远不会有的编译器 任何已定义的副作用并且永远不会返回23可以用“return 42;”替换“foo”的代码。即使程序的目的是测试functionWithNoSideEffects是否会返回42(在这种情况下生成的代码返回42,无论函数是否有用)标准都不需要编译器生成代码来实际测试它,除非循环包括某种“副作用”。

我个人并不相信拥有一条规则的价值 如果编译器可以显示循环不能在没有X的情况下终止,那么它们 可以认为X是否为真,无论是否有任何方法 可能。然而,基于该原则的优化似乎很受欢迎。