PeaceSheep's blog PeaceSheep's blog
首页
  • 分类
  • 标签
  • 归档
相关链接
提建议&咨询&赞赏
GitHub (opens new window)

PeaceSheep

以最简洁、易懂的话解决问题
首页
  • 分类
  • 标签
  • 归档
相关链接
提建议&咨询&赞赏
GitHub (opens new window)
  • C++

    • Visual Studio莫名报链接器错误的BUG
    • 关于C++循环体没有可观察行为被编译器优化而导致的BUG
      • 问题描述
      • 尝试的可能
      • 原因(不完全确定)
  • Python

  • Go

  • java

  • 语言
  • C++
PeaceSheep
2025-03-12
目录

关于C++循环体没有可观察行为被编译器优化而导致的BUG

在写题目283. 移动零 (opens new window)的时候遇到的,仅仅是一个cout就会导致一个if条件的变化。

# 问题描述

如果运行下面的代码,会得到“超出时间限制”。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        size_t p1=0;
        while(true)
        {
            cout<<endl;
            if(  (p1==nums.size()) || (nums[p1]==0) )
            {
                cout<<"ABC"<<endl;
                break;
            }
        }
    }
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

如果运行下面的代码(仅仅是把cout << endl注释),所有样例会输出"ABC"并且break(比如样例4的输入是[2,1]也会break)。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        size_t p1=0;
        while(true)
        {
            //cout<<endl;
            if(  (p1==nums.size()) || (nums[p1]==0) )
            {
                cout<<"ABC"<<endl;
                break;
            }
        }
    }
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

为什么只是加了一个cout就会导致结果不同?if条件应该是false。怀疑和编译器优化有关?

最神奇的是,在if里面把if的条件输出是0。

# 尝试的可能

  1. if后面多加了分号导致if自己变成了一条语句?

仔细检查了下并没有多加。

  1. 有内存越界等UB行为?

看了下感觉没有?如果nums.size()是0,由于短目性会直接条件为真,也就不会访问到nums[p1]这个位置。

# 原因(不完全确定)

根据知乎 (opens new window)、github有关llvm的issue (opens new window),基本可以确定是编译器优化导致的,可以认为是编译器的BUG。

根据C++ ISO标准规定,如果一个死循环内部没有“可观察行为”,则允许编译器将其删除从而进行优化。

假设这个循环被编译后这条指令的入口地址是A,里面有一个if,编译的时候if里面的内容编译后的入口地址报放到了循环的后面,假设是地址B,if成功会跳转到这个地址B执行。

巧合的是,B正好在A的下面,也就是B=A+1。

理论上的表现应该是,运行到A,进入循环体,if不成立,因为while从而跳回到A,这样往复死循环。

但是编译器把这个空循环优化了,导致pc跳过循环直接跑到了循环下面,也就是从A直接运行到了A+1。而此地址A+1正好是本来应该if跳转的位置B,也就是if里面的内容,所以表现就是运行了if里面的东西,实际上是因为运行的时候跳过了这个循环,直接跑到了这个本应该是if跳转过来的地址。

编辑 (opens new window)
上次更新: 2025/04/15, 10:52:45
Visual Studio莫名报链接器错误的BUG
django3实现Websocket最简单demo

← Visual Studio莫名报链接器错误的BUG django3实现Websocket最简单demo→

最近更新
01
ubuntu安装g++显示已有但是输入g++又找不到命令
04-15
02
使用cloudflare-r2搭建webdav
04-08
03
LLM聚合平台客户端对比
03-29
更多文章>
Theme by Vdoing | Copyright © 2022-2025 PeaceSheep
冀ICP备2022004632号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式