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

记一次死循环不生效问题

在这里插入图片描述

看如下代码,本意是我们模拟一次死循环,然后会在中断处理函数中更改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
使用示例
中断处理函数改变变量值
跳出死循环
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cider瞳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值