VS编译器优化诱发一个的Bug
VS编译器优化诱发一个的Bug
Bug的背景
我正在把某个C++下的驱动程序移植到C下,前几天发生了一个比较诡异的问题。
驱动程序有一个bug,但是这个bug只能 Win32 Release 版本下的驱动才能重现。在 Win32 Debug 版本下,和 Win64 Release/Debug 版本下均无法重新。
随着一步步的分析,最终发现问题是由于VS编译器的一个优化诱发的。当然这并不是VS编译器的bug,只是由于优化诱发程序里面的某个bug.
调试的思路
1. Debug Vs Release
首先想到的自然是看看Debug版本和Release版本运行是有啥区别了。Release版本本质上和Debug版本没啥区别,一样都可以使用调试器调试,只不过有些大大小小需要注意的地方罢了。基本上熟知编译器的优化原理和调试器,调试Release版本的程序也不是啥困难的事情。
一般导致Debug和Release不同的常见问题无非下面这些,未初始化的局部变量,程序指针访问越界,多线程同步问题。而这些问题都是很容易发现的,但随着调试的深入,并没有发现这些问题的踪迹,反而所有的代码都工作的很好,没啥异常发生。对比Debug和Release版本下的流程,Release版本的问题在于在某个时候硬件没有如期的触发中断。但在这之前两个版本所执行的代码逻辑完全一样,没有啥区别。
问题越发诡异了。
2. 32bit Vs 64 bit
既然64bit Release的版本没有问题,但32bit Release有问题,这也是一个突破的思路。
把相关的代码拿出来仔细梳理,注意看一些32/64bit下的常见问题,诸如指针大小,整数溢出等问题。不过依然没有发现问题。
3. 编译器的优化
Debug和Release的最大的区别自然是编译器的优化不同,但是哪个编译器不是久经考验,要是说编译器上出问题,那真是撞了大运了,所以没有第一时间考虑是由于优化造成的。不过既然直接调试代码没发现问题的所在,那只有使用另外一种分析方法了,那就是不断缩小导致问题的范围。
既然我手上有两个版本,一个好的,一个坏的。那只要不断缩小两个版本之间的不同,最终就能定位到导致问题的部分。
所以第一个拿来开刀的自然是编译器的优化选项。几经尝试,终于发现诱发问题的编译器优化是这一项,Favor Size Or Speed. 诡异,真是相当的诡异呀。不过无所谓,既然找到了这一个线索,下面就好找了。这个优化只是一个函数内的局部优化,只要针对不同的函数分别打开和关闭这个优化,自然就能发现问题所在了。
问题的根源
针对一些可疑的代码,分别打开和关闭这个Favor Size Or Speed的优化,不断的缩小范围之后,最终定位到某个函数是罪魁祸首。然后比较了一下生成的汇编代码,最后定位到了下面这行语句
pDevice->pReg->S = 0xFFFFFFFF;
而这行代码生成的汇编代码如下:
or dword ptr [eax+10h],0FFFFFFFFh //Release版本,Favor Size优化
mov dword ptr [eax+10h],0FFFFFFFFh //Debug版本,无优化
乍一看一定会觉得这个诡异,因为or和mov指令在这里的逻辑其实是一模一样的,编译器没有任何错误。那为何会有不同的执行效果呢?
其实原因在于pDevice->pReg->S并不是一个普通的内存地址,他是一个MMIO(memory mapped IO) address地址。也就是说这个变量并不存在于内存里面,而是硬件的某个寄存器,只不过和内存共用了一个地址空间。而对于这种MMIO address,虽然可以直接象访问普通内存一样读写他们,但最安全的方式还是使用Windows提供的函数,所以对于这个bug的修复是
WRITE_REGISTER_ULONG(&pDevice->pReg->S,0xFFFFFFFF);
至于为啥会出这种乌龙,其实就是一开始移植的时候粗心大意了。pDevice->pReg->S = 0xFFFFFFFF; 这句C++语句中的=其实一个重载过的C++运算符,内部的实现就是WRITE_REGISTER_ULONG,移植过来的时候也没有细看具体哪个S是个什么东西,就抄过来了
VS编译器优化诱发一个的Bug的更多相关文章
- 【转】C 编译器优化过程中的 Bug
C 编译器优化过程中的 Bug 一个朋友向我指出一个最近他们发现的 GCC 编译器优化过程(加上 -O3 选项)里的 bug,导致他们的产品出现非常诡异的行为.这使我想起以前见过的一个 GCC bug ...
- 探索c#之尾递归编译器优化
阅读目录: 递归运用 尾递归优化 编译器优化 递归运用 一个函数直接或间接的调用自身,这个函数即可叫做递归函数. 递归主要功能是把问题转换成较小规模的子问题,以子问题的解去逐渐逼近最终结果. 递归最重 ...
- 翻译「C++ Rvalue References Explained」C++右值引用详解 Part6:Move语义和编译器优化
本文为第六部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...
- gcc编译器优化给我们带来的麻烦???
gcc编译器优化给我们带来的麻烦??? 今天看到一个很有趣的程序,如下: ? 1 2 3 4 5 6 7 8 9 int main() { const int a = 1; int * ...
- C#编译器优化那点事
使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的. 优化代码开关即optimize开 ...
- C#编译器优化那点事 c# 如果一个对象的值为null,那么它调用扩展方法时为甚么不报错 webAPI 控制器(Controller)太多怎么办? .NET MVC项目设置包含Areas中的页面为默认启动页 (五)Net Core使用静态文件 学习ASP.NET Core Razor 编程系列八——并发处理
C#编译器优化那点事 使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的.优化代码 ...
- C#编译器优化
C#编译器优化 https://www.cnblogs.com/podolski/p/8987595.html 使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置 ...
- js动画--一个小bug处理下
对于上面的课程我们很好的处理了一个小bug,那么我们现在讲程序进行优化一下,前一节的程序中,我们处理处理的属性都是写死了的.为了我们能够很好的对某个属性进行操作的话.我们这样来设置. js文件 win ...
- 2018-8-10-win10-uwp-禁止编译器优化代码
title author date CreateTime categories win10 uwp 禁止编译器优化代码 lindexi 2018-08-10 19:16:50 +0800 2018-2 ...
随机推荐
- 面试问题-使用Java线程做数学运算
这是一个展示如何使用join()方法的例子. 问题: 使用Java多线程计算表达式1*2/(1+2)的值. 解决方案: 使用一个线程做加法运算,另一个线程做乘法运算,还有一个主线程main做除法运算. ...
- HTML基础(三)——css样式表
CSS(Cascading Style Sheet,叠层样式表),作用是美化HTML网页. /*注释区域*/此为注释语法 一.样式表 (一)样式表的分类 1.内联样式表 和HTML联合显示,控制精确, ...
- Sqlite学习笔记(三)&&WAL性能测试
WAL是SQLite3.7.0版本引入的一个重大改进.SQLite官网宣称在很多使用场景下,WAL模型的性能都要好于默认的DELETE模式.下面将针对几个主要场景对WAL性能做测试,测试的硬件与xxx ...
- CentOS 6.2编译安装Nginx1.2.0+MySQL5.5.25+PHP5.3.13
CentOS 6.2编译安装Nginx1.2.0+MySQL5.5.25+PHP5.3.132013-10-24 15:31:12标签:服务器 防火墙 file 配置文件 written 一.配置好I ...
- 设计模式C#实现(十)——桥接模式
意图 0 适用性 1 结构 2 实现 3 效果 4 意图 将抽象部分与它的实现部分分离,使它们都可以独立的变化. 适用性 1.不希望抽象和实现间有固定的绑定关系2.类的抽象以及它的实现都可以通过生成子 ...
- 006.udp转发包并代理访问服务器总结
背景: 当加速器(client)拦截了游戏客户端发送的完整数据包(package)时,将package传给中间服务器(mid_server),经过自己的链路传输数据之后,中间服务器模拟游戏客户端将数据 ...
- 探究C语言中的前++和后++
小波带您探究c语言中的前++与后++: 欢迎吐槽,欢迎加QQ463431476. 欢迎关注! 现在来探究: 咱们先看第一个 i被赋值0,i++(后++)并没有输出1. 现在i被赋值0,++i,也 ...
- hadoop2.6---常用命令
为了方便操作,可以把hadoop加入环境变量 修改,vi ~/.bashrc export HADOOP_PREFIX=/app/programs/hadoop- export HADOOP_MAPR ...
- [转]OnKeyDown Numeric Validator CLIENT SIDE
本文转自:http://forums.asp.net/t/1211724.aspx?OnKeyDown+Numeric+Validator+CLIENT+SIDE <!DOCTYPE html ...
- 认识与入门 Markdown,Markdown教程
一.认识 Markdown 在刚才的导语里提到,Markdown 是一种用来写作的轻量级「标记语言」,它用简洁的语法代替排版,而不像一般我们用的字处理软件 Word 或 Pages 有大量的排版.字体 ...