这个是今天在微信群里讨论的一个问题,先看图片

点击查看大图

代码流程大概是这个样子的

点击查看大图

查看 lengthspace1 的值,明显看到 length 小于 space1 的值,即使是这样小白都能搞懂流程的情况下,代码还是跑到else里面区执行

调试查看数据

然后 我们就在群里讨论,有的大神说这个是内存越界,也有大神说可能是人品有问题,也有大神说这个是因为写代码前没有选好一个良辰吉日,反正大家想法都非常多,也非常古怪,这可能就是讨论群存在的一个原因了。

经过不断的验证,发现这个问题是因为编译器优化的问题

如果在设置里面把优化选项去掉代码就执行正确

编译器对代码优化

当然还有一个问题,就是如果我想开启优化,毕竟代码太大占用的存储空间是很大的,如果能节省点空间是最好的了。所以就出现了一种,只针对某些代码不优化的设置

像这样

我们使用GCC编译的时候,也是有可能因为代码优化导致这样的问题的,庆幸的是,GCC也有设置不进行优化的开关。

#使用GCC编译器设置选择性不优化某段代码

#pragma GCC push_options
#pragma GCC optimize ("O0")
#pragma GCC pop_options

push 的意思是把当前的编译优化选项压栈,然后再设置当前的优化选项,之后再出栈,把之前压栈的选项提取出来。

具体可以参考链接:

https://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Function-Specific-Option-Pragmas.html

链接里面还介绍了一些其他的用法,原文如下

5.52.12 Function Specific Option Pragmas
#pragma GCC target ("string"...)
This pragma allows you to set target specific options for functions defined later in the source file. One or more strings can be specified. Each function that is defined after this point will be as if attribute((target("STRING"))) was specified for that function. The parenthesis around the options is optional. See Function Attributes, for more information about the target attribute and the attribute syntax.
The `#pragma GCC target' pragma is not implemented in GCC versions earlier than 4.4, and is currently only implemented for the 386 and x86_64 backends.#pragma GCC optimize ("string"...)
This pragma allows you to set global optimization options for functions defined later in the source file. One or more strings can be specified. Each function that is defined after this point will be as if attribute((optimize("STRING"))) was specified for that function. The parenthesis around the options is optional. See Function Attributes, for more information about the optimize attribute and the attribute syntax.
The `#pragma GCC optimize' pragma is not implemented in GCC versions earlier than 4.4.#pragma GCC push_options
#pragma GCC pop_options
These pragmas maintain a stack of the current target and optimization options. It is intended for include files where you temporarily want to switch to using a different `#pragma GCC target' or `#pragma GCC optimize' and then to pop back to the previous options.
The `#pragma GCC push_options' and `#pragma GCC pop_options' pragmas are not implemented in GCC versions earlier than 4.4.#pragma GCC reset_options
This pragma clears the current #pragma GCC target and #pragma GCC optimize to use the default switches as specified on the command line.
The `#pragma GCC reset_options' pragma is not implemented in GCC versions earlier than 4.4.

#当然还有指定某个函数设置优化等级

int max(int a, int b) __attribute__((optimize("O0")));
{return a < b ? a : b;
}

#使用volatile 关键字避免编译器优化

volatile 的作用是提醒CPU,如果遇到被volatile 修饰的变量,要从内存里面去取值,而不要偷懒,直接从缓存里面取值,我们一般是用在那些被中断处理函数使用的那些变量。

如果有些代码,你不希望CPU偷懒,那你就可以加上volatile ,让CPU从内存取数据。

CSDN上有这样一个例子

https://blog.csdn.net/qq_28637193/article/details/88988951今天碰到一个gcc优化相关的问题,为了让一个页变成脏页(页表中dirty位被置上),需要执行下面这段代码:1 uint32_t *page;
2 // ...
3 page[0] = page[0];
最后一行代码很有可能被gcc优化掉,因为这段代码看起来没有任何实际的作用。那么如何防止gcc对这段代码做优化呢?设置gcc编译时优化级别为-O0肯定是不合适的,这样对程序性能影响会比较大。stackoverflow上的Dietrich Epp给出了一个强制类型转换的方案:((unsigned char volatile *)page)[0] = page[0];
通过volatile关键字禁止gcc的优化

#总结、什么情况会导致这样的问题?

1、堆栈溢出应该是一个原因,之前我有遇到的情况是栈空间设置太小,然后溢出到堆空间导致问题。

2、使用某个函数导致溢出,我们使用的函数,比如,内存拷贝函数,如果长度设置不对,也会导致影响到其他的代码。

3、还有就是上面说的编译器优化导致的问题。

评论说说你在开发过程总遇到过哪些奇葩的问题,又是如何解决的呢?

#推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号 

代码优化导致的奇葩问题相关推荐

  1. 多么痛的领悟-代码优化导致的BUG

    一大早服务器报警,top一下,系统CPU负载已经飚到了15,导致无法访问! jstack pid打印堆栈,大量解析json的线程在RUNNABLE. 忽然想到之前为了json解析的效率,放弃了现成的类 ...

  2. 三宝机器人怎么充电_巨人通力导致吉祥三宝+36号故障怪现象的又一因素

    想必大家都有过这样的经历:在电梯故障频繁出现时,明明可以判断是哪里的问题,但事实却是让你感觉不可思议,并且排查过程颇为周折. 今天和大家分享一下我经历的巨人通力GPS30K电梯出现的吉祥三宝故障的排查 ...

  3. mac book pro 灰屏 屏幕闪烁 色差 低温 重物导致压迫

    mac book pro 灰屏 低温 重物导致压迫 奇葩的问题吧,我遇到两次了,第一次好像是长途火车回来,开机灰屏,(屏幕不是没反应,是灰屏,)开机无启动logo 等一会,屏幕背部logo是亮的,第二 ...

  4. Node.js中的express框架,修改内容后自动更新(免重启),express热更新

    有两个插件可以解决此问题:1)supervisor:2)nodemon. 今天我只讲supervisor如何安装.设置开机自动启动: 强调一下!用supervisor来启动nodejs,就不用用什么p ...

  5. 全局变量引起的BUG

    花费3个小时解决了一个问题,时间比较长. 这次问题的原因是全局变量引起的,一个实例的函数用到了全局变量计算一个值,而全局变量的这个值会进行改变,所以在不同时期算出来的值是不一致的.而调用这个实例函数的 ...

  6. 《最终幻想7 重制版》DEMO体验:讨论ATB战斗系统的一些问题

    仅基于DEMO,正式版让我们共同期待 刚刚通关,我个人对这个DEMO的评价还是比较高的,整个玩下来流程不长,大概半小时到四十分钟,但是刚刚好,节选选的相当合适,在一个小情节里把该展示的都给玩家展示了, ...

  7. NSURLProtocol概述

    一.概念 NSURLProtocol也是苹果众多黑魔法中的一种,使用它可以轻松地重定义整个URL Loading System.当你注册自定义NSURLProtocol后,就有机会对所有的请求进行统一 ...

  8. jmap+MAT实战内存溢出

    一.堆区和非堆区 前言: 如果发生内存溢出,主要是通过内存映像文件,来查看到底是那些类,一直在占有没有释放. 1.1 情况分析: 第一种内存溢出:有可能内存泄漏 第二种内存溢出:也有可能内存分配不足导 ...

  9. jenkins+Xcode+蒲公英实现ipa自动打包发布全攻略

    http://www.jianshu.com/p/ed124917d6c6 蒲公英:https://www.pgyer.com/udid/ 一步快速获取 iOS 设备的 UDID 请使用 iPhone ...

最新文章

  1. TVM部署和集成Deploy and Integration
  2. 一个简单的Ajax开发框架
  3. DevExpress WPF v18.2新版亮点(四)
  4. eclipse 关闭时progress information弹框_Spring开发环境搭建(Eclipse)
  5. 1290. 二进制链表转整数
  6. sklearn查看数据
  7. Cocos2d-x场景功能描述的生命周期
  8. iOS开发 - StoryBoard + UIScrollView + UIView
  9. C语言实实验步骤,C语言教程学习方法攻略
  10. 堆栈应用(三):火车车厢重排
  11. 怎么保护自己的音乐作品不被盗用,用FL制作防盗水印片段。
  12. C语言编程>第二周 ① 打印菱形图案
  13. (干货,建议收藏)备战2021年软考中级网络工程师-02操作系统
  14. Vue项目:IE11中地址栏直接改变路由页面不跳转bug
  15. C#快递单号查询源码
  16. 在DeSmuME模拟器上成功运行AK2i的内核,破解AK2i命令集
  17. ar vr内容制作_AR和VR品牌内容:探索与观众建立联系的新方式
  18. C语言学习笔记-有符号数和无符号数相加的问题
  19. wdcp-apache配置错误导致进程淤积进而内存吃紧
  20. Vue+element ui上传图片和视频并回显,点击放大查看和播放

热门文章

  1. 解决 windows10和ubuntu16.04双系统下时间不对的问题
  2. JAVA中toString方法的作用(转)
  3. Linux系统目录结构及主要内容
  4. 《我的成长》6月下2009年第7期(总第7期)
  5. java上传rar文件_java实现上传zip/rar压缩文件,自动解压
  6. git 拉取远程其他分支代码_【记录】git 拉取远程分支代码,同步到另一个git上...
  7. 深度学习之 SSD(Single Shot MultiBox Detector)
  8. Python 内置模块之 logging
  9. table取tr对象 vue_Vue笔记
  10. 一行Python代码制作动态二维码