搜索
bottom↓
回复: 26

MDK的bug还是我的bug----volatile被优化

[复制链接]

出0入0汤圆

发表于 2010-5-3 18:36:29 | 显示全部楼层 |阅读模式
程序没有开中断,其实MDK也不会识别你有没有开中断(其实我是在开中断的时候试出来的)下面的语句while里面翻译错了~,声明我用的是D版


typedef unsigned long ulong;

volatile ulong *Pt;

int main(void)
{
        volatile ulong i;
        Pt = &i;
        while(1)
        {
                *(volatile ulong *)0x50004000 = i;
        }                 
}

void SysTick_Handler(void)
{
        ++*Pt;
}

上面的volatile变量翻译的不对,汇编如下:
                 main:
0x00000168 B508      PUSH     {r3,lr}
0x0000016A 4906      LDR      r1,[pc,#24]  ; @0x00000184
0x0000016C 4668      MOV      r0,sp
0x0000016E 6008      STR      r0,[r1,#0x00]
0x00000170 4905      LDR      r1,[pc,#20]  ; @0x00000188
0x00000172 9800      LDR      r0,[sp,#0x00]
0x00000174 6008      STR      r0,[r1,#0x00]
0x00000176 E7FD      B        0x00000174                这里一直这样循环,也没有加载过程,郁闷ing,优化级别调到最低没事~
                 SysTick_Handler:
0x00000178 4802      LDR      r0,[pc,#8]  ; @0x00000184
0x0000017A 6800      LDR      r0,[r0,#0x00]
0x0000017C 6801      LDR      r1,[r0,#0x00]
0x0000017E 1C49      ADDS     r1,r1,#1
0x00000180 6001      STR      r1,[r0,#0x00]
0x00000182 4770      BX       lr

大家看看,是不是用D版都会这样?还是我的表达有问题~希望是我哪里写错了。我用的是MDK V4.03

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2010-5-3 19:52:26 | 显示全部楼层
看不出有什么问题啊,i是局部变量,本来就会放在寄存器中而不需要加载。

出0入0汤圆

 楼主| 发表于 2010-5-3 19:57:00 | 显示全部楼层
volatile应该不分的呀,即使是局部变量我既然声明成了volatile那么他就要去源地址去取东东呀

出0入0汤圆

发表于 2010-5-3 19:57:05 | 显示全部楼层
把 i 定义成全局变量试试?!

还有,LZ用的编译程序版本多少?

出0入0汤圆

 楼主| 发表于 2010-5-3 20:27:28 | 显示全部楼层
回复【3楼】linnjing
把 i 定义成全局变量试试?!
还有,lz用的编译程序版本多少?
-----------------------------------------------------------------------

全局的就变味道啦(全局可以),关键是局部的volatile就不管用了吗,郁闷ing

我的版本是

(原文件名:未命名.jpg)

出0入0汤圆

发表于 2010-5-3 20:32:16 | 显示全部楼层
en 编译器的错误。

GCC是这样的:
main:
        sub     sp, sp, #8
        ldr     r3, .L5
        add     r0, sp, #4
        mov     r2, #1342177280
        str     r0, [r3, #0]
        add     r2, r2, #16384
.L2:
        ldr     r1, [sp, #4]
        str     r1, [r2, #0]
        b       .L2
.L6:
        .align  2
.L5:
        .word   Pt

出0入0汤圆

 楼主| 发表于 2010-5-3 21:07:03 | 显示全部楼层
回复【5楼】minux 啊啊?
en 编译器的错误。
gcc是这样的:
main:
        sub     sp, sp, #8
        ldr     r3, .l5
        add     r0, sp, #4
        mov     r2, #1342177280
        str     r0, [r3, #0]
        add     r2, r2, #16384
.l2:
        ldr     r1, [sp, #4]
        str     r1, [r2, #0]
        b       .l2
.l6:
        .align  2
.l5:
        .word   pt

-----------------------------------------------------------------------
这样倒是合理
.L2:
        ldr     r1, [sp, #4]
        str     r1, [r2, #0]
        b       .L2

出0入0汤圆

发表于 2010-5-3 21:17:35 | 显示全部楼层
这个要看编译器的说明,里面一定有讲的,volatile的作用范围

出0入0汤圆

发表于 2010-5-3 21:36:39 | 显示全部楼层
试试最新版,估计应该会修正这个问题

出0入0汤圆

发表于 2010-5-3 21:49:29 | 显示全部楼层
那再这样试试,

*(volatile ulong *)0x50004000 = *Pt

其实感觉这样做比较正常

typedef unsigned long ulong;

volatile ulong i;

int main(void)
{
while(1)
{
*(volatile ulong *)0x50004000 = i;
  }   
}

void SysTick_Handler(void)
{
++i;
}

你这样做算什么?检测KEIL MDK?!你这就是变着法的折腾嘛!!
不如这样,把这个问题问问Keil,搞不好算你发现了一个BUG,keil回头送你一套正版的也说不定呢

出0入0汤圆

发表于 2010-5-3 22:17:29 | 显示全部楼层
回复【楼主位】david_ming  
-----------------------------------------------------------------------

LZ这么写代码不是太好的习惯。有点类似于考察编译器的推断行为。
LZ的代码总的来说,都是对i的读操作,无论是i的地址还是i的数据。对这种情况,编译器可以有不同的选择:A,对volatile的变量不优化,每次操作必须造成内存访问;B,跟踪对i的各种引用关系和操作,决定何种程度的优化;C,单纯看对volatile变量自身的引用关系,决定何种优化。

Keil可能用的是C;GCC可能是A;B的消耗太高,估计不会有人用。。。
这个问题,应该说,不应该是编译器的Bug;而是采用了不够良好的描述,在编译器的优化策略下导致的问题。估计LZ用的Keil也不是Debug模式的。

出0入0汤圆

发表于 2010-5-3 22:20:40 | 显示全部楼层
【7楼】 dianzidog

volatile的语义是C标准里明确定义的。

出0入0汤圆

发表于 2010-5-3 22:42:54 | 显示全部楼层
咦?局部变量谁来改它?

出0入0汤圆

发表于 2010-5-3 23:49:34 | 显示全部楼层
LZ,你是不是吃饱了?

出0入0汤圆

 楼主| 发表于 2010-5-4 11:15:54 | 显示全部楼层
用局部变量是因为尽量提高代码的复用性,我写的这个代码是精简化了的,我的两个程序是在不同的文件里边,Systick函数是单独的一个文件,然后include进来,上面的代码只是验证一下KEIL

出0入0汤圆

发表于 2010-5-4 13:39:49 | 显示全部楼层
尝试给一个明确写操作,避免只读优化:i = (volatile unsigned long *)(&i);在While前边,试试看吧。

尽管不清楚你为什么不在i上加个static。毕竟你的pt是全局的,要可重入也不是这样的啊。

出0入0汤圆

 楼主| 发表于 2010-5-4 14:13:15 | 显示全部楼层
回复【15楼】dr2001
尝试给一个明确写操作,避免只读优化:i = (volatile unsigned long *)(&i);在while前边,试试看吧。
尽管不清楚你为什么不在i上加个static。毕竟你的pt是全局的,要可重入也不是这样的啊。
-----------------------------------------------------------------------

只要是使 i 分配在全局区域的关键字都可以正确执行,问题锁定在局部变量的volatile是不是比较矛盾

出0入0汤圆

发表于 2010-5-4 14:43:05 | 显示全部楼层
回复【16楼】david_ming  
-----------------------------------------------------------------------
我所说的方式,和把i放在全局区域或赋予全局的生存期,都没有关系。因为LZ位代码中,对volatile的i没有任何写操作,因而编译器完成了只读优化。那么,我们在While的前边,加入一个volatile的写操作,可能会导致编译器放弃对i的只读优化。

局部作用域,局部生存期的动态变量,volatile的,还是未见直接写入的(编译器处理的时候,看到的都是Read操作),要不要优化呢……
另外,引用一个未初始化的自动变量。。。也不是说是个编译器就能弄清楚的行为。

出0入0汤圆

 楼主| 发表于 2010-5-4 15:21:27 | 显示全部楼层
回楼上,用你的方法报错如下:

main.c(12): error:  #513: a value of type "volatile ulong *" cannot be assigned to an entity of type "ulong"

出0入0汤圆

发表于 2010-5-4 15:59:54 | 显示全部楼层
【17楼】 dr2001

不啊,加了volatile后,编译器就不应该做那些优化了。
尤其是编译器可以推断出i的地址并非绝对不会有写入,因为已经给全局变量赋予过&i了(同时那个全局指针还是volatile ulong *类型)。
按照编译器的行为方式,只要不能确保不会在别的地方写入的volatile变量,肯定是不能做只读优化的。

总之肯定是编译器对于volatile的处理有误。

出0入0汤圆

 楼主| 发表于 2010-5-4 16:03:32 | 显示全部楼层
我在问问KEIL的FAE,英文不太好

出0入0汤圆

 楼主| 发表于 2010-5-4 17:53:45 | 显示全部楼层
看来真像是的MDK的bug,那个FAE说要去向Team反映

出0入0汤圆

发表于 2010-5-4 22:08:56 | 显示全部楼层
i不是static哦

出0入0汤圆

发表于 2019-1-31 22:01:11 | 显示全部楼层
无意中看到这帖子,这么好的主题成为烂尾楼岂不可惜了
RVMKD编译器是嵌入式IDE里遵守C标准的典范,所以不要轻易怀疑它的语法BUG。
第一,按照C语言规范,类型限定符(volatile 和 const)只有通过左值访问时才会起作用,而楼主程序里的变量“ i ” 始终是作为右值访问的,编译器可以对它执行优化。
第二,volatile 关键字并不是要求编译器对某个对象不要执行优化,它的确切的含义是:对某个对象的优化不能跨越序列点。如何理解这句话?虚拟世界实验室的《重入与线程安全性解惑》对此做了精确的解释。

出0入4汤圆

发表于 2019-1-31 22:39:22 来自手机 | 显示全部楼层
laoshuhunya 发表于 2019-1-31 22:01
无意中看到这帖子,这么好的主题成为烂尾楼岂不可惜了
RVMKD编译器是嵌入式IDE里遵守C标准的典 ...

楼上好厉害,学习了

出0入296汤圆

发表于 2019-1-31 23:22:39 | 显示全部楼层
Arm Compiler 5.06的volatile优化bug在之前的版本中的确存在过……只不过基本上都不是中国人发现的……默默飘过。
考虑到大家生存不易,代码能运行结果对就行了,我就不强求所有人遇到问题都像邻国从业人员那样打破砂锅问到底了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 01:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表