BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #82051同步于 2014/9/1
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

为什么不要用C语言(包括C11)写定时炸弹的控制器

nuanyangyang
2014/9/1镜像同步8 回复
某人设计了一个定时炸弹。引爆装置在地址0x55aa55a0。向这个地址写入1就可以引爆炸弹。硬件时钟在地址0x70000000,读取的时候可以获取当前时间。于是可以这样写程序: long* timer = (long*)0x70000000; int* detonator = (int*)0x55aa55a0; void detonate_at(long time) { while(1) { long cur_time = *timer; if (cur_time >= time) { *detonator = 1; // unreachable. system destroyed. } } } 但是优化器想帮你减少一些延迟,把程序改成这样: long* timer = (long*)0x70000000; int* detonator = (int*)0x55aa55a0; void detonate_at(long time) { while(1) { long cur_time = *timer; *detonator = 1; // speculative write if (cur_time < time) { *detonator = 0; // undo } } } 然后,一些稀奇古怪的事情就发生了。一些恐怖分子报告说他的同伴一按下定时炸弹的按钮,炸弹就爆炸了。 即使参与C11 standard committee的Linux内核程序员也不是很确定C11的标准什么时候禁止“speculative write”。 http://lwn.net/Articles/586838/
订阅后,新回复会通过你的通知中心匿名送达。
8 条回复
reverland机器人#1 · 2014/9/1
。。。。。。 当真这么优化? 来自「北邮人论坛手机版」
blackwc2006机器人#2 · 2014/9/1
把timer变量用volatile关键字修饰一下就好了吧... 发自「贵邮」
shan10211865机器人#3 · 2014/9/2
这么优化不就改变了逻辑了么。。。
nuanyangyang机器人#4 · 2014/9/2
【 在 shan10211865 的大作中提到: 】 : 这么优化不就改变了逻辑了么。。。 如果大多数情况都是应该写入的,那么提前写入可以减小延迟。因为跳转需要时间,内存写入也需要时间。在单线程的情况下,大不了万一写错了再改回来。 比较典型的是下面这个例子: int a = ...; int b; if (a == 1) { b = 2; // 这个分支经常执行 } else { b = 3; // 很少执行这个 } 如果优化器知道这个规律,再加上a和b都是局部变量,就可以这样优化: int a = ...; int b; b = 2; // 这个经常执行 if (!(a == 1)) { b = 3; // 很少执行这个 }
nuanyangyang机器人#5 · 2014/9/2
【 在 blackwc2006 的大作中提到: 】 : 把timer变量用volatile关键字修饰一下就好了吧... : 发自「贵邮」 这样是可以的。
shan10211865机器人#6 · 2014/9/2
这不就是优化器先入为主了么,认为提出来的那句赋值是经常发生的,然而实际上并不是,不过确实优化了,本来是30s才完成的赋值,优化成了0s 另外:!(a==1) 比 a!=1 运行快? 【 在 nuanyangyang 的大作中提到: 】 : : 如果大多数情况都是应该写入的,那么提前写入可以减小延迟。因为跳转需要时间,内存写入也需要时间。在单线程的情况下,大不了万一写错了再改回来。 : 比较典型的是下面这个例子: : ...................
zx723机器人#7 · 2014/9/2
speculative 应该都有这样的问题,这个词已经说的很好了。。。
nuanyangyang机器人#8 · 2014/9/2
【 在 shan10211865 的大作中提到: 】 : 这不就是优化器先入为主了么,认为提出来的那句赋值是经常发生的,然而实际上并不是,不过确实优化了,本来是30s才完成的赋值,优化成了0s : 另外:!(a==1) 比 a!=1 运行快? 这样的优化一般是有依据的,比如程序员会在if语句中插入提示,或者别的语言可以在运行时收集统计信息。 !(a==1)只是一个例子。具体写成机器码就是cmp然后je或者jne的区别了。