当前位置: 首页 > article >正文

编译器优化乌龙——记一次死循环不进入问题

记一次死循环不生效问题

在这里插入图片描述

看如下代码,本意是我们模拟一次死循环,然后会在中断处理函数中更改waiting的值,更改waiting的值后,跳出死循环。

int waiting = 0;
while(waiting==0)
    {

    }

运行起来发现,程序根本就没有进入这个死循环,究其原因。
因为编译器将其优化了,正确做法应该是使用 volatile 关键字:在 C/C++ 中,volatile 关键字可以告诉编译器变量可能会在程序的控制之外改变,因此编译器不会优化掉对它的读写操作。

所以我们更改后为

volatile int waiting = 0;
while(waiting==0)
    {

    }

程序正常执行死循环。

volatile关键字

在C和C++编程语言中,volatile 关键字是一种类型修饰符,用于告诉编译器该变量的值可能会在程序的控制之外被改变。这意味着每次使用这个变量时,编译器都必须从内存中重新读取它的值,而不是使用寄存器中的值或者缓存的值。编译器不会对 volatile 变量进行优化,以确保程序的行为与变量可能的外部变化保持同步。

用途:

硬件寄存器访问:在嵌入式编程中,volatile 通常用于访问硬件寄存器,因为硬件寄存器的值可能会被外部设备或中断服务程序改变。
多线程编程:在多线程环境中,volatile 可以用于声明共享变量,以确保每次访问都是最新的值,防止编译器对这些变量进行优化。
信号处理:在信号处理函数中,volatile 可以用于声明全局变量,以确保在主程序和信号处理程序之间正确同步变量的值。

编译器行为:

编译器不会对 volatile 变量进行寄存器优化,即不会将变量的值存储在寄存器中,而是每次访问时都从内存中读取。
编译器不会对 volatile 变量进行指令重排优化,即不会改变涉及 volatile 变量的指令的执行顺序。
内存模型:

在C++11及以后的版本中,volatile 被分为两种:C/C++风格的 volatile 和C++11中的 std::atomic。std::atomic 提供了更严格的内存模型保证,而 volatile 只保证变量的值可能在程序的控制之外改变。

使用示例:

volatile int flag = 0;

void interruptHandler() {
    // 这个中断服务程序可能会改变flag的值
    flag = 1;
}

void main() {
    while (flag == 0) {
        // 即使flag的值没有改变,编译器也会在每次循环时重新读取flag的值
        // 因为flag被声明为volatile
    }
    // 处理flag为1的情况
}

全文流程

记一次死循环不生效问题
模拟死循环
程序未进入死循环
原因分析
编译器优化导致
解决方案
使用 volatile 关键字
程序正常执行死循环
volatile关键字解释
用途
硬件寄存器访问
多线程编程
信号处理
编译器行为
不进行寄存器优化
不进行指令重排优化
内存模型
C/C++风格的 volatile
C++11中的 std::atomic
使用示例
中断处理函数改变变量值
跳出死循环

http://www.kler.cn/a/382993.html

相关文章:

  • LLMs之Calculate:利用大语言模型技术基于文本内容实现数字计算能力的简介、常用方法、代码实现之详细攻略
  • 大模型微调技术 --> 脉络
  • 【网络安全】|nessus使用
  • Linux——Linux基础指令
  • 冒泡排序、选择排序、计数排序、插入排序、快速排序、堆排序、归并排序JAVA实现
  • Linux网络命令:它用于实时监控网络接口的状态变化的命令 ip monitor详解
  • Elasticsearch Interval 查询:为什么它们是真正的位置查询,以及如何从 Span 转换
  • aitrader产品规划:数据自动下载,策略,因子挖掘,实盘对接,gui界面(源码+数据)
  • 重构代码之移动方法
  • 数据挖掘(六)
  • CentOS 9 Stream 上安装 Nginx
  • 【c知道】Hadoop工作原理。
  • 前后端交互接口(三)
  • 设置服务器ssh连接超时时间
  • 51单片机学习心得2(基于STC89C52):串口通信(UART)
  • 动态库实现lua网络请求GET, POST, 下载文件
  • 龙蜥副理事长张东:加速推进 AI+OS 深度融合,打造最 AI 的服务器操作系统
  • Java 中的 `wait()` 与 `sleep()`:深入解析两者的不同
  • SQLite数据库是什么?DB Browser for SQLite是什么?
  • Python 在PDF中绘制形状(线条、矩形、椭圆形等)
  • keep-alive - 2024最新版前端秋招面试短期突击面试题【100道】
  • A02、JVM性能监测调优
  • Docker学习—Docker核心概念总结
  • 机器学习—矩阵乘法
  • NeurIPS24 | 多无人机协作精确预测车辆等目标移动轨迹, Drones Help Drones
  • 【comfyui教程】ComfyUI即将迎来全新界面:升级体验就在11月15日