原文:http://www.thinksaas.cn/topics/0/484/484804.html

我们知道在C语言编译时,有那么几个常用的优化编译选项,分别是-O0,-O1,-O2,-O3以及-Os。之前一直觉得既然是优化选项,顶多是优化一下逻辑,提高一些效率或者减少一下程序大小而已。很少会觉得它们会影响程序的最终结果。直到最近在ARM平台上发现一个程序里的一个bug,才觉得这些优化选项有时候也没那么智能。或者说针对ARM平台,还没有那么智能。
      首先看这么一段程序,此程序是我将问题简单化的程序:

#include<stdio.h>
#include<string.h>
int main()
{  char buffer[1024] = {0,1,2,3,4,5,6,7};
  int iTest = 0x12345678;//16进制1位表示4个bit,itest表示4个byte
  int *p = (int *)(buffer + 7);//指针+数字表示表示截取数组,buffer第7位开始以后的数组
   printf("intlen: %d itestlen:%d itest:%d\n",sizeof(int),sizeof(iTest),iTest);
  memcpy(p, &iTest, sizeof(iTest));//iTest
  printf("%x\n", buffer[6]);
  printf("%x\n", buffer[9]);
  return 0;
}

乍看之下,觉得这个程序没啥问题。然后我们将此程序文件名称叫point.c。然后分别用交叉编译链进行如下编译:
    arm-xxx-linux-gcc point.c -o point0 -O0
    arm-xxx-linux-gcc point.c -o point1 -O1
    arm-xxx-linux-gcc point.c -o point2 -O2
    最终再分别执行三个程序,结果却有点出人意料:
    ./point0
    6
    34
    ./point1
    34
    0
    ./point2
    6
    0
    只有在-O0,也就是没有优化的情况下,结果才和假想的一致。但是同样的问题在x86平台上却没有问题。
    于是我通过用以下命令,分别来生成不同优化选项下的汇编代码,来确定在ARM平台上编译到底出了什么问题。
    arm-xxx-linux-gcc point.c -o point0.s -O0 -S
    arm-xxx-linux-gcc point.c -o point1.s -O1 -S
    arm-xxx-linux-gcc point.c -o point2.s -O2 -S
    然后对比三个汇编的代码,发现问题出在memcpy这句话上。
    在point0.s中,程序是老老实实的调用的memcpy,然后就将0x12345678老老实实按照字节一个个的放到了buffer+7的位置。
    而在point1.s中程序则是没有调用memcpy,而是用的语句:
    str        r3, [sp, #7]
    而此时r3中存储的就是0x12345678;而由于我采用的ARM平台是32位的,此语句执行时,地址线应该不会发生变化,所以最终的结果是buffer+4到buffer+7的数据被覆盖了,而不是buffer+7到buffer+10的数据被修改。
    而在point2.s中,貌似又针对流水线进行了优化,程序执行顺序会有所变化,在对buffer部分位置赋初值的顺序是在str  r3, [sp, #7]之后,所以buffer+6处的数据反而是正确的6。
    分析到这儿,也许有人会说写个简单的程序,都会因为编译的优化选项不同导致结果不同,那这memcpy是不是就不敢用了?
    其实一般只要有较好的编程习惯的话,都不会遇到此类问题,比如下面的程序:

#include<stdio.h>
#include<string.h>int main()
{char buffer[1024] = {0,1,2,3,4,5,6,7};int iTest = 0x12345678;char *p = buffer + 7;memcpy(p, &iTest, sizeof(iTest));printf("%xn", buffer[6]);  printf("%xn", buffer[9]);   return 0;
}

这段程序其实只是简单的改变了p的类型,就能保证在各种优化下,结果都一样。可见好的编程习惯是有多么的重要。

优化选项对ARM下指针赋值的影响相关推荐

  1. ARM嵌入式编译器编译优化选项 -O

    Arm嵌入式编译器可以执行一些优化来减少代码量并提高应用程序的性能.不同的优化级别有不同的优化目标,不仅如此,针对某个目标进行优化会对其他目标产生影响.比如想减小生成的代码量,势必会影响到该代码的性能 ...

  2. gcc 优化选项 -O1 -O2 -O3 -Os 优先级

    Gcc 编译优化简介 gcc 提供了为了满足用户不同程度的的优化需要,提供了近百种优化选项,用来对{编译时间,目标文件长度,执行效率}这个三维模型进行不同的取舍和平衡.优化的方法不一而足,总体上将有以 ...

  3. makefile工作笔记0002---gcc -O0 -O1 -O2 -O3 四级优化选项及每级分别做什么优化

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 相关博客http://blog.chinaunix.net/uid-24954950-id-295 ...

  4. gcc 优化选项 -O1 -O2 -O3 -Os 优先级,-fomit-frame-pointer(不积跬步无以至千里)

    -fomit-frame-pointer 在优化时候被启用,带来了效率的提升.看到一篇比较详细记录编译选项的文章,转发一下,同时给自己作一下备忘. 少优化->多优化: O0 -->> ...

  5. gcc -O0 -O1 -O2 -O3 四级优化选项及每级分别做什么优化【转】

    转自:http://blog.csdn.net/qinrenzhi/article/details/78334677 相关博客http://blog.chinaunix.net/uid-2495495 ...

  6. gcc -O0 -O1 -O2 -O3 四级优化选项及每级分别做什么优化

    相关博客http://blog.chinaunix.net/uid-24954950-id-2956476.html 相关博客http://blog.csdn.net/misiter/article/ ...

  7. 多核服务器的JVM优化选项(转载)

    原文链接 现在多核CPU是主流.利用多核技术,可以有效发挥硬件的能力,提升吞吐量,对于Java程序,可以实现并发垃圾收集.但是Java利用多核技术也带来了一些问题,主要是多线程共享内存引起了.目前内存 ...

  8. Keil MDK 编译器 AC5 和 AC6 优化选项重要内容和区别

    关注.星标公众号,不错过精彩内容 整理:黄工 参考来源:Arm官网 使用过Keil MDK (Arm Compiler 6)编译器V6版本的读者应该发现了一个问题,V6版本速度比V5版本编译速度快很多 ...

  9. GCC编译器优化选项分析及具体优化了什么

    问题 在使用gcc作为编译器.在设定编译条件时,在debug模式下生成的程序正常,但是在release模式下往往会出现很多种预料之外的结果,尤其在嵌入式环境中,程序在板子上运行的时候,问题就愈发明显. ...

最新文章

  1. zabbix全网监控介绍
  2. 网站推广专员浅析高指数关键词优化网站推广如何推至首页?
  3. SpringBoot 配置文件 application.properties(二)
  4. Git迁移 从SVN到Git
  5. 你为什么喜欢VIM?
  6. 通过JDBC和Hibernate对Clob和Blob的操作
  7. Linux 部署ASP.NET SQLite 应用 的坎坷之旅 附demo及源码
  8. win10系统安装SQL Server2005中文版安装教程和下载地址(亲测成功)
  9. 小程序wxParse
  10. finereport java无符合资料_Java报表工具FineReport常见的数据集报错错误代码和解释...
  11. 若依ruoyi框架整合magic-api增删改查Demo
  12. Python和MD5网站挂马检测程序
  13. NC65 用户密码重置
  14. 我的思文斋:积水成渊则蛟龙生焉
  15. 实时可视化大数据项目02 -- 项目目录介绍
  16. spring——事务动态代理造成属性为null
  17. securecrt下传输大文件
  18. Java----枚举类的使用
  19. 程序人生|五年java 含泪总结,建议小白看
  20. linux文件属性详细说明(网络转载,仅供学习之用)

热门文章

  1. 全国计算机一级ms office考试难吗,全国计算机等级考试一级msoffice难考吗?_联展教育问答...
  2. ios开发 ajax hook,IOS中的网络拦截总结
  3. 南京林业大学计算机专升本,2018江苏专转本学校之:南京林业大学
  4. predicate java 作用_Java函数式编程接口详解之Predicate
  5. 中美程序员的不完全对比,看看跟你了解的一样吗?
  6. 云服务商正在杀死开源商业模式
  7. Java 实现第三方 QQ 账号登录
  8. 手把手教你定制标准 Spring Boot starter
  9. 盘点几种MySQL复制的解决方案和常见的错误理解
  10. 说说我为什么看好Spring Cloud Alibaba