代码优化导致的奇葩问题

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

点击查看大图

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

点击查看大图

查看 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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467148.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度:关于Linux内核最硬核的文章

来源 &#xff1a;头条号Linux学习教程&#xff0c;冰凌块儿01前言本文主要讲解什么是Linux内核&#xff0c;以及通过多张图片展示Linux内核的作用与功能&#xff0c;以便于读者能快速理解什么是Linux内核&#xff0c;能看懂Linux内核。拥有超过1300万行的代码&#xff0c;Linu…

springaop----springaop的使用(一)

与大多数技术一样&#xff0c; AOP 已经形成了自己的术语。描述切面的常用术语有通知&#xff08;advice&#xff09;、切点&#xff08;pointcut&#xff09;和连接点&#xff08;join point&#xff09;。从今天开始&#xff0c;我们对spring的切面编程做一个总结。她们都是你…

Microsoft .NET Pet Shop 4 架构与技术分析

1&#xff0e;项目概述与架构分析微软刚推出了基于ASP.NET 2.0下的Pet Shop 4, 该版本有了一个全新的用户界面。是研究ASP.NET 2.0的好范例啊&#xff0c;大家都知道&#xff0c;一直以来&#xff0c;在.NET和Java之间争论不休&#xff0c;到底使用哪个平台开发的企业级应用性能…

想领取开发套件,就来参加AIoT开发者大赛

你心目中的智慧校园长什么样&#xff1f; 传统校园上自习得排队等位&#xff0c;智慧校园手机一键查询空位&#xff0c;抢座占位有序便利&#xff1b; 传统校园灯光全靠手动调整&#xff0c;智慧校园灯光无感调控&#xff0c;营造全新智能光照环境&#xff1b;传统校园安全防护…

[教程]win10 ,ubuntu双系统安装避坑指南

这篇博客可以解决1.如何安装win10,ubuntu双系统2.如何使用win10引导Ubuntu&#xff0c;并且设置win10引导界面点击阅读原文获取更多信息。win10,ubuntu双系统的安装为什么要装双系统&#xff0c;之前用的虚拟机&#xff0c;但是虚拟机没有显卡&#xff0c;使用gazebo之类的3D仿…

Type-C PD充电简介

一、Type-C简介自1998年以来&#xff0c;USB发布至今&#xff0c;USB已经走过20个年头有余了。在这20年间&#xff0c;USB-IF组织发布N种接口状态&#xff0c;包括A口、B口、MINI-A、MINI-B、Micro-A、Micro-B等等接口形态&#xff0c;由于各家产品不同&#xff0c;不同产品使用…

Linux字符设备驱动内幕

哈喽&#xff0c;我是老吴&#xff0c;继续记录我的学习心得。一、保持专注的几个技巧将最重要的事放在早上做。待在无干扰环境下&#xff0c;比如图书馆。意识到刚坐下开始投入工作前&#xff0c;有点负面小情绪是特别正常的现象。让“开心一刻”成为计划的一部分。拥有合情合…

旧地重游

光阴飞逝1991年跟随父母搬迁至长沙&#xff0c;至今已有16年。2007年春节舅妈大寿借此机会回到儿时旧地以了多年来的心愿。经过1个小时左右颠簸终于快回到儿时生长的地方&#xff0c;那里的路面年久失修&#xff0c;经过昨天的大雨&#xff0c;已经坑坑洼洼路面到处积水&#x…

我要不要离职?

1#读者提问来到四线城市的小公司&#xff0c;其他员工都是公司主动找到他们转正的&#xff0c;有的一个月有的三个月&#xff0c;而我半年过去了&#xff0c;以为时间到了也跟他们一样自动帮我转正。然而没有&#xff0c;昨天忍不住问了公司&#xff0c;今天就拿转正表来给我填…

搞懂进程组、会话、控制终端关系,才能明白守护进程干嘛的?

守护进程概念&#xff1a;守护进程&#xff0c;也就是通常所说的Daemon进程&#xff0c;是Linux中的后台服务进程。周期性的执行某种任务或等待处理某些发生的事件。Linux系统有很多守护进程&#xff0c;大多数服务都是用守护进程实现的。比如&#xff1a;像我们的tftp&#xf…

关于编译C#文件

使用csc.exe编译非控制台应用程序,常使用/target选项此选项可简写为/t,用来指定要创建的文件类型. 如编译一个类库文件(dll)Class1.cs: namespaceTest...{ /**//// <summary> /// Class1 的摘要说明。 /// </summary> public class Class1 ...{ …

【速来抢】iPhone12、STM32开发板、1024元现金红包…打包免费送!!!

没错&#xff01;华清远见在做1024狂欢节活动今年他们“玩”的有点大参与活动&#xff0c;抽取幸运锦鲤下面21件惊喜大礼&#xff0c;打包全部带回家????参与方式&#xff1a;扫码下方二维码&#xff0c;进活动群获取抽奖链接&#xff0c;参与抽奖????福利2除了万元锦鲤…

1024,第 15 届「中国内核开发者大会」 参会指南(议程全剧透)

各位好&#xff0c;第 15 届「中国内核开发者大会」即将开幕&#xff0c;这些参会指南请提前收藏好&#xff1a;2020「中国内核开发者大会」&#xff08;以下简称 CLK&#xff09;将在 2020 年 10 月 24 日举办&#xff0c;线上线下同步进行&#xff0c;线上由 CSDN 进行全网直…

1024对话内核大神谢宝友

我看了CSDN的采访&#xff0c;感觉比较官方&#xff0c;不知道是不是编辑的原因把一些内容给隐藏了&#xff0c;所以我还是想完整的内容放出来给大家看看&#xff0c;这些问题&#xff0c;可能是很多后辈程序员非常关心的。今天是1024节&#xff0c;这个数字对于写在电脑前写代…

javascript 里Array的一些方法

1. join()方法&#xff1a;join()方法的用途是连接字符串值&#xff0c;join()方法只有一个参数&#xff0c;即数组项之间使用的字符串如&#xff1a;varaColors ["red","green","blue"];alert(aCloors.join("-"));//output "red…

很多人都不清楚HEX文件格式

Intel HEX文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中&#xff0c;每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。Intel HEX文件通常用于传输将被存于ROM或者EPROM中的程序和数据。大多数EPR…

如何在asp.net中实现listbox item值上下移动?(转)

全部.net为&#xff1a;1 <form id"myform"runat"server">2 <div>3 <asp:ObjectDataSource ID"ObjectDataSource1"runat"server"OldValuesParameterFormatString"original_{0}"4 …

洛谷1345 [Usaco5.4]奶牛的电信

题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系&#xff0c;于是她们建立了一个奶牛电脑网络&#xff0c;以便互相交流。这些机器用如下的方式发送电邮&#xff1a;如果存在一个由c台电脑组成的序列a1,a2,...,a(c)&#xff0c;且a1与a2相连&#xff0c;a2与a3相连&#xff0c;…

有意思,USB资料分享

前几天&#xff0c;有个同学在微信问我 「发哥&#xff0c;能不能给我分享一些USB的资料吗&#xff1f;」-- 然后就有了今天的文章。我对USB印象很深&#xff0c;源于两个事情第一件事情是&#xff0c;我有一个大学同学&#xff0c;他的名字里面有一个「发」字&#xff0c;我们…