首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

关注细节:整数溢出的故事

练习题

为什么我们使用c = a + (b – a) / 2这个公式,而不是更简单的c = (a + b) / 2?

答案

为了在计算[a + b]时可能出现的整数溢出。在这个例子中,a和b都是窗口的坐标值,而且这个窗口可能会位于任何位置。如果恰巧窗口被放置到了一个极端的位置,例如(MAXLONG,MAXLONG),则公式中的算术运算可能出现溢出,导致的结果是,中间点的坐标值可能计算错误。

请注意,我们使用的版本[a + (b – a) / 2]也是有可能出现溢出的,但是在我们的例子中,[b – a]的值是窗口的宽度值,而这个宽度是我们可以控制的。

我曾经碰到过的一个Windows 95上的兼容性问题,就是由整型溢出导致的。那个时候,有一个DOS的游戏,开发者想执行一项二进制搜索,他们尝试直接对两个指针求平均值,而不是使用复数,如下所示:

BYTE *low = …;

BYTE *high = …;

BYTE *mid = ((UINT)low + (UINT)high)/2;

以上的代码可以在操作系统没有启用虚拟内存时很好的工作,因为在这种环境下,”low”和”high”这两个指针相对来说会是很小的值(那个时候,没有人的机器拥有2GB的内存),所以它们两个的和不会出现溢出。

Windows 95运行了这些DOS游戏,但是它运行在一台支持虚拟内存的DPMI服务器上。DPMI规范允许服务器将内存指向任意位置,我们将内存指向了可用地址空间的高地址的位置。

可想而知,这个程序在尝试计算两个指针的平均值的时候出现了溢出,进而导致整个程序的崩溃。

所以,当你计算两个值之和的时候,请特别小心,因为程序实际的运行情况可能和你预想的不一样。

总结

两个看起来在数学上完全等效的两个公式,在计算机看来确实两种不同的结果。

(敲黑板)细节,还是细节啊。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200429A0RFF600?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券