volatile 是个坑

volatile 是个坑。

volatile 关键字是告诉编译器,不要把这个变量放到寄存器里。

我们先来看一段代码:

#include <iostream>
#include <csignal>

int flag = 1;

void MyHandler(int signal)
{
    (void)signal;
    flag = 0;
    std::cout << "flag = 0, Process exit." << std::endl;
}

int main(void)
{
    signal(SIGINT, MyHandler);
    while (flag)
    {
        ;
    }

    return 0;
}

在这里插入图片描述

当我们使用 ctrl + c 发送信号的时候,会将 flag 改为0,所以程序就不会无休止的循环下去了。

但是如果我们把编译器优化开到2,会发生什么呢?

Makefile

Main:Main.cpp
	g++ -o $@ $^ -std=c++11 -O2

.PHONY:clean
clean:
	rm Main

在这里插入图片描述

我们可以看到,不管我按多少次 ctrl + c 程序都不会终止。

原因:

  • 我把编译器优化开到2之后,由于while循环要频繁读取 flag 到寄存器中,编译器就会判定为这是一个 比较高的开销,另一方面,编译器没检测到有哪个代码要修改 flag(MyHandler 函数是由内核调用的,编译器并不知道),编译器就出现了错误判断,就直接把 flag 这个值优化到寄存器中。
  • 所以,ctrl + c 改了flag 之后,flag并不会被读取,cpu继续读取寄存器中的 flag。

解决办法:

volatile int flag = 1;

我们在 flag 之前使用 volatile 关键字,就是告诉编译器不要把这个变量放到寄存器中,才能使程序达到我们想要的结果。

在这里插入图片描述

结论:

所以 volatile 关键字是一个没有办法的办法,总的来说还是编译器没办法解决这个问题,所以需要我们手动添加关键字。

叮~ ?

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值