arm下gcc编译添加 -Ox 优化后,程序无法正常运行
一、问题描述
今天学习正点原子的阿尔法开发板裸机开发的时候,遇到了一个问题,在没有使用 -Ox 优化的时候,编译出来的程序能够正常运行,但是添加了-Ox之后,程序运行就出了问题。
二、问题查找与解决
最开始还以为是自己敲的代码和视频中的代码出入比较大,影响到了程序的运行,不过事实证明(发现过程比较复杂,这里就不详写了),也确实是,下面是两者的差异代码,前者是我自己写的,后者是视屏中的:
//我写的
void Delay(volatile unsigned int n) {
unsigned int n_s = 0;
while(n --) {
n_s = 0x7FF;
while(n_s --);
}
}
//官方例程
void Delay_Short(volatile unsigned int n)
{
while(n--){}
}
void Delay(volatile unsigned int n) {
while(n--) {
Delay_Short(0x7ff);
}
}
在逻辑上确实没啥大问题,但是编译出来的效果却截然不同,后者能够正常运行,前者运行就是异常的,最终发现,差异就在一个平时很少见的关键词 volatile
,我写的 unsigned int n_s = 0;
就没有添加 volatile
前缀,后面把前缀加上,问题就解决了,程序也能正常运行了。
//以下代码能够正常运行
void Delay(volatile unsigned int n) {
volatile unsigned int n_s = 0;
while(n --) {
n_s = 0x7FF;
while(n_s --);
}
}
三、总结
本次问题的最终问题就出在一个关键词上边,做了三年的嵌入式开发了,遇到使用 volatile
关键词来修饰的变量屈指可数,一直觉得这个关键词不重要,唯一影响深刻的就是在学习 stm32 的时候,正点原子介绍一种叫做位带操作的时候出现过一次,其他时候出现的概率都很小,不过最主要还是没遇到过 -Ox
这种编译优化,今天也是无意中遇到了,然后特意学习了一下,明白了大致原因,经过 -Ox
编译优化处理过后的一些数据会被一直放在寄存器中,内存不会对其进行再次写入操作,所以他的值得不到改变,所以最终导致了程序运行异常,这种操作叫做 内存覆盖
,所以程序会运行异常。
参考博文:
1.《C语言关键字详解(五)带你全面了解 volatile 关键字》
https://blog.csdn.net/m0_62391199/article/details/123746218
2.《C语言丨深入理解volatile关键字》
https://blog.csdn.net/m0_53157173/article/details/129344954
学习分享,一起成长!以上为小编的经验分享,若存在不当之处,请批评指正!