相关疑难解决方法(0)

优化"while(1);" 在C++ 0x中

更新,见下文!

我听说并读过C++ 0x允许编译器为以下代码段打印"Hello"

#include <iostream>

int main() {
  while(1) 
    ;
  std::cout << "Hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

它显然与线程和优化功能有关.在我看来,这可能让许多人感到惊讶.

有人能够很好地解释为什么必须允许这样做吗?作为参考,最新的C++ 0x草案说明了6.5/5

在for语句的情况下,在for-init语句之外的循环,

  • 不调用库I/O函数,和
  • 不访问或修改易失性对象,以及
  • 不执行同步操作(1.10)或原子操作(第29条)

可以通过实现来假设终止.[注意:这是为了允许编译器转换,例如删除空循环,即使无法证明终止也是如此. - 结束说明]

编辑:

这篇富有洞察力的文章谈到了标准文本

不幸的是,没有使用"未定义的行为".但是,只要标准说"编译器可以假设P",就暗示具有非-P属性的程序具有未定义的语义.

这是正确的,是否允许编译器为上述程序打印"Bye"?


这里有一个更有见地的线索,这是关于C的类似改变,由Guy完成上述链接文章开始.在其他有用的事实中,他们提出了一个似乎也适用于C++ 0x的解决方案(更新:这将不再适用于n3225 - 见下文!)

endless:
  goto endless;
Run Code Online (Sandbox Code Playgroud)

看来,编译器不允许优化它,因为它不是循环,而是跳转.另一个人总结了C++ 0x和C201X的建议更改

通过编写一个循环,程序员断言或者环路不可见的东西的行为(执行I/O,访问volatile对象,或执行同步或原子操作), 或者,它最终会终止.如果我通过编写一个没有副作用的无限循环来违反这个假设,我对编译器撒谎,而我的程序的行为是未定义的.(如果我很幸运,编译器可能会警告我.)语言不提供(不再提供?)表达无可见行为的无限循环的方法.


2011年3月3日更新为n3225:委员会将案文移至1.10/24并说

实现可以假定任何线程最终将执行以下操作之一:

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

的goto把戏,不工作了!

c++ optimization loops c++11

150
推荐指数
5
解决办法
1万
查看次数

编译器是否允许消除无限循环?

可以优化编译器删除无限循环,这不会改变任何数据,如

while(1) 
  /* noop */;
Run Code Online (Sandbox Code Playgroud)

从分析编译器可以推导出的数据流图,这样的循环是"死代码"而没有任何副作用.

是否删除了C90/C99标准禁止的无限循环?

C90或C99标准是否允许编译器删除此类循环?

更新:"Microsoft C版本6.0基本上做了这个优化.",请参阅caf的链接.

label: goto label;
return 0;
Run Code Online (Sandbox Code Playgroud)

将转变为

return 0;
Run Code Online (Sandbox Code Playgroud)

c compiler-construction optimization standards infinite-loop

30
推荐指数
3
解决办法
5512
查看次数

24
推荐指数
2
解决办法
3000
查看次数

术语"空循环"在C和C++中究竟是指什么?

这是这样的事情:

for(;;)
 {
   statements;
 }
Run Code Online (Sandbox Code Playgroud)

或者是这样的:

for(initialisation;condition;updation)
{
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找各种来源的答案.

c c++

23
推荐指数
2
解决办法
3万
查看次数

当 X 不成立时,“实现可能假设 X”意味着未定义的行为?

最近有人试图说服我cppreference是错误的,因为它说没有副作用的无限循环将是未定义的行为。与无限循环是否未定义相关的一个问题是无限循环与无限递归。两者都是未定义的吗?。接受的答案引用了标准并得出结论:是的,没有副作用的无限循环是未定义的行为。

其他相关问题有:

相关引用是([basic.progress]p1):

该实现可能假设任何线程最终都会执行以下操作之一:

  • 终止,
  • 调用库 I/O 函数,
  • 通过易失性左值执行访问,或者
  • 执行同步操作或原子操作。

当标准说“实现可能假设 X”时,这种措辞是否意味着包含“非 X”的代码未定义?

(在这个例子中,这意味着egfor (;;);是未定义的,但我很好奇该措辞的一般含义)

c++ undefined-behavior language-lawyer

3
推荐指数
1
解决办法
223
查看次数

为什么 clang 会优化轮询另一个线程写入的变量的循环?

当我学习 C++ 时,我发现了一些奇怪的东西......
我认为下面的代码会产生大数的结果(至少不是 1.1)。
相反,结果是在此处输入图像描述

其他编译器按预期工作。
但是具有积极优化的 clang 编译器似乎忽略了 while 循环。
所以我的问题是,我的代码有什么问题?还是clang有意为之?

我使用了apple clang编译器(v14.0.3)

#include <iostream>
#include <thread>


static bool should_terminate = false;

void infinite_loop() {
    long double i = 1.1;
    while(!should_terminate)
        i *= i;
    std::cout << i;
}

int main() {
    std::thread(infinite_loop).detach();
    std::cout << "main thread";
    for (int i = 0 ; i < 5; i++) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::cout << ".";
    }
    should_terminate = true;
}
Run Code Online (Sandbox Code Playgroud)

来自编译器资源管理器的汇编结果(clang v16.0.0,-O3)
这似乎也跳过了 while 循环。

_Z13infinite_loopv:                     # @_Z13infinite_loopv
        sub     rsp, 24 …
Run Code Online (Sandbox Code Playgroud)

c++ optimization multithreading clang data-race

2
推荐指数
1
解决办法
225
查看次数

C处的线程同步

我必须使用两个线程; 一个用于对矩阵进行各种操作,另一个用于监视矩阵运算过程中各个点的虚拟内存.使用全局状态变量'flag'需要此方法.

到目前为止,我有以下内容(为简洁而留下一些):

int flag = 0;

int allocate_matrices(int dimension)
{
    while (flag == 0) {} //busy wait while main prints memory state

    int *matrix = (int *) malloc(sizeof(int)*dimension*dimension);
    int *matrix2 = (int *) malloc(sizeof(int)*dimension*dimension);

    flag = 0;
    while (flag == 0) {} //busy wait while main prints memory state

    // more similar actions...
}

int memory_stats()
{
    while (flag == 0)
    { system("top"); flag = 1; }
}

int main()
{ //threads are created and joined for these two …
Run Code Online (Sandbox Code Playgroud)

c multithreading synchronization

1
推荐指数
2
解决办法
1万
查看次数