
问题代码重现:
上面代码中,我们不(hen)难发现,在GetByte时我们需要将原来32位的DWORD先右移8的倍数位(由于32/8 = 4,我们有四种选择,所以移位可以写成(3 - off)*8 ),然后再与上0xff就好了。
好了,这个函数是OK的。重点来了,我们发现下面这个GetWord函数,在移位时,由于32位取高16位或者低16位,只有两种选择,所以这里正确写法应该是(1 - off)*16,不过我们这里竟然也是(3 - off)。
问题来了,这样的后果是什么,off肯定是0或1的,由于写成了3 - off,我们最终移的是48或者32位。
问题分析:
咦,上面不是已经分析完了吗?
No,这么简单还能叫做狡猾吗?
说它狡猾就是因为这个接口我们经常用,而且快一年了,从没发现任何问题,是不是好神(dou)奇(bi)。
不信是不?
你们可以自己试试,将一个32位数右移48或者32位,看看结果,会颠覆三观的。
到这里,可能有些同学又要提问了,既然都没问题,为啥还叫Bug?
别急,这里让你三观再次颠覆的事情发生了,它真的就这样发生了。
换成 release模式你再试试(我默认大家平时调程序都是在debug下进行的),是不是发现结果变成了0了?
好吧不卖关子了,为了抓住这只狡猾的Bug,我们的攻城狮们浴血奋战,终于在汇编层发现了一些蹊跷。
在debug模式下:我们发现原来移48位和32位分别变成移16位和0位;
而在release模式下,这行代码直接被优化掉了。
查询手册探究问题根源:
为了验证我们的猜想,特意去查了选相关文档。
Intel手册中关于SHR指令的说明:
C++(11)标准:
到这里终于真相大白了,对于这个Bug,表示根本没辙啊,单元测试一般也是在Debug下运行的。所以我们在做白盒测试时,代码的静态检查一定要做好,对于这种问题,我们仍要去努(ting)力(tian)发(you)现(ming)。
如需转载该篇文章,请注明来自“搜狗测试”