算术溢出

本页使用了标题或全文手工转换,现处于中国大陆简体模式
求闻百科,共笔求闻

算术溢出(arithmetic overflow)或简称为溢出(overflow)指的是:

  1. 电脑领域里所发生的溢出条件是,执行单项数值计算时,当计算产生出来的结果是非常大的,大于寄存器记忆体所能储存或表示的能力限制。
  2. 在电脑领域里,执行多项或累计的数值计算时,当计算产生出来的总值是非常大的,大于寄存器或记忆体所能储存或表示的能力限制。要注意的是,溢出可能会在其他地址被置换。[来源请求]

加法器中央处理器算术逻辑单元中的核心之一。当长度为n位的两个二进制数经过加减法器运算,得到的长度为n位的结果不是正确值时,我们说发生溢出

检查溢出

大多数的电脑都可以区别以上两种溢出条件。当运算的数值与结果都是无符号整数类型,并且运算的结果不能被该类型容纳时,加法或减法的结果就会发生进位。所以,在执行无符号整数的加法或减法之后检查进位旗标是非常有用的做法。在运算结果的符号不应是由操作数的符号产生时(例如两个正整数相加产生的结果为一个负数),很可能发生溢出。所以,在执行补码的加法或减法之后检查溢出旗标是非常有用的作法(换言之,认为其是有符号整数)。

控制溢出

有几个控制溢出的方法:

  1. 设计:选择正确的数据类型,尤其要注意资料长度与资料符号。
  2. 回避:事先注意指令的运作以及检查运算的数值,或许可以确保计算出来的结果不会超过记忆体储存资料的限制
  3. 控制:当它被侦测到,还有在其他的程序完成时被检测出来,那么溢出是可以被预料的。例如:两个比特大的两个数值做加法计算,这种情形最可能发生。步骤如下:先加低比特再加高比特,但是如果它必须完成低比特的运算,就会产生比特加法的运算溢出,那么就有必要做侦测和增加高比特的总和。通常CPU有支持侦测数值加法大于寄存器大小的作法,基本上这个作法是采用状态比特的方式。
  4. 增值:假如储存的数值过大就会被分配给其他特定的数值,这时溢出就会发生,然后传回旗标值时就会产生连续运作的现象。检查这个问题最有用的方法,就是在整体的计算结尾做一次性的检查工作,而不是检查每一个执行步骤。这个作法最常用在浮点硬体调用浮点运算器
  5. 忽略:这是最普遍的作法,但是这个作法会得出不正确的结果,以及降低程序的安全性

除零计算

任何数除以零的计算(Divided by zero)“不是”算术溢出的一种。在数学上只能明显算是不明确的定义(Undefined);它计算出来的结果只能当成是“没有”值,而不是非常大的无限数值。

例子

意外的算术溢出是程序错误的常见原因。此类错误难以发现和诊断,因为它们可能仅对于非常大的输入数据表现出来,而这些数据不太可能被用于验证测试。

在许多搜索算法中,将两个数字相加再除以二以计算平均值,如果两数之和(哪怕平均值不是)太大而无法表示,并因此溢出,则会导致错误。

发动机转向软件中未处理的算术溢出是 1996 年阿丽亚娜5型运载火箭首飞坠毁的主要原因。 [1][2]

Error message due to an integer signedness bug in the stack setup code of MASM 1.00.gif
Pascal 编译器产生的堆栈设置代码中的整数符号错误阻止了 IBM–Microsoft 宏汇编器 (MASM) 版本 1.00,一个 1981 年的 DOS 程序,以及许多其他使用相同编译器编译的程序,在某些超过 512 KB 内存的配置下运行。

IBM–Microsoft 宏汇编器 (MASM) 版本 1.00,以及由同一 Pascal 编译器构建的所有其他程序,在堆栈设置代码中存在整数溢出和符号错误,这阻止它们在较新的具有超过 512 KB 内存配置的 DOS 机器或模拟器上运行。如果运行,则程序挂起或显示错误消息,并退出到 DOS。[3]

相关参见

  1. Wired.com: "History's Worst Software Bugs" (Retrieved 3 September 2009)
  2. Ariane 5 Flight 501 Failure, Report by the Inquiry Board (PDF). esamultimedia.esa.int. [2015-10-17]. 
  3. Lenclud, Christophe. Debugging IBM MACRO Assembler Version 1.00.