在計算機程式設計中，當算術運算試圖建立一個超出可用位數表示範圍（大於最大值或小於最小值）的數值時，就會發生整數溢位錯誤。 整數溢位的表現形式可分為：無符號整數上溢、無符號整數下溢、有符號整數上溢、有符號整數下溢。 整數溢位錯誤會導致軟體運算結果出錯，1996 年亞利安 5 號運載火箭爆炸，2004 年 Comair 航空公司航班停飛事故都是整數溢位造成的。 來源 處理器的暫存器寬度決定了暫存器中可表示值的範圍。雖然大部分計算機可以對記憶體運算元完成多精度算術，允許對任意位數的值進行操作，避免溢位，但是暫存器寬度限制了每個操作（例如加法或減法）只需要一個指令的數的大小。典型的無符號整數二進位制暫存器寬度包括： 4 位：最大可表示值 24 1 15 8 位：最大可表示值 28 1 255 16 位：最大可表示值 216 1 65535 32 位：最大可表示值 232 1 4294967295 （截止到 2005 年個人電腦最普通的寬度）， 64 位：最大可表示值 264 1 18446744073709551615 （截止到 2021 年個人電腦中央處理器（CPU）的最普通寬度）， 128 位：最大可表示值 2128 1 340282366920938463463374607431768211455 當無符號算術運算產生大於 N 位整數最大值的結果時，溢位使結果對 2 的 N 次方取模，只保留結果的最低 N 位，有效地引起 繞回。 例如，兩個整數相乘或相加可能會產生小到預期之外的結果，數值較小的整數被減至負數時可能繞回到一個大正數。（例如，8 位整數加法 2552 的結果是 1，也就是 257mod 28，相似的，減法 01 的結果是 255，是 1 的補碼錶示）。 這種繞回可能會導致安全性損害 如果溢位的值被用作分配給緩衝區的位元組數，則將被分配的緩衝區會意想不到的小，可能導致緩衝區溢位。根據緩衝區的使用情況，這可能會導致任意程式碼執行。 如果變數是有符號整數型別，程式可能會假定它總是包含一個正的值。整數溢位可導致值被繞回，成為負數，違背了程式的假定，可能產生意料之外的結果（例如，8 位整數加法 1271 的結果是 128 它是 128 的補碼）。這個特定問題的解決方案是於程式中必然為正數的值使用無符號整數型別。 標識位 大多數計算機都有兩個專用的處理器標識位來檢查溢位情況。 當加法或減法的結果（將運算元和結果視為無符號數）不符合給定的位數時，設定為 1。 這表示帶有從最高有效位進位或借位的溢位。 緊隨其後的帶有 帶進位的加法 或 帶借位的減法 操作將使用該標誌的內容來修改包含該多字值較高部分的暫存器或記憶體。 當對有符號數的運算結果沒有從運算元的符號中預測的符號時，設定為 1，例如，將兩個正數相加時的結果為負數。 這表明發生了溢位，並且以補碼形式表示的帶符號結果不符合給定的位數。 定義變種和歧義 對於無符號型別，當操作的理想結果在該型別可表示範圍之外，且返回結果被繞回時，這次事件通常被定義為溢位。作為對照，C11 標準定義這類事件不是溢位，並聲稱 包含無符號運算元的運算不可能溢位。 當整數運算的理想結果在該型別可表示範圍之外，且返回結果被限制時，這次事件通常被定義為飽和。溢位是否是飽和的，會使使用有所不同。 為了消除歧義，可以使用術語溢位時繞回和溢位時飽和。 術語下溢最常用於浮點數學而不是整數數學。算術下溢 但是，可以找到許多對整數下溢的引用。 當使用術語整數下溢時，這意味著理想結果比輸出型別的可表示值更接近負無窮大。 當使用術語整數下溢時，溢位的定義可能包括所有型別的溢位，或者它可能只包括理想結果比輸出型別的可表示值更接近正無窮大的情況。 當一個操作的理想結果不是一個精準整數時，在邊緣情況下溢位的含義可能是模稜兩可的。 考慮理想結果的值為 12725 並且輸出型別的最大可表示值為 127 的情況。如果將溢位定義為理想值超出輸出型別的可表示範圍，那麼這種情況將被歸類為溢位。 對於具有明確舍入行為的操作，溢位分類可能需要推遲到應用舍入之後。 C11 標準定義從浮點到整數的轉換必須向零舍入。 如果使用 C 將浮點值 12725 轉換為整數，則應首先應用舍入以給出理想的整數輸出 127。由於舍入後的整數在輸出範圍內，C 標準不會將此轉換歸類為溢位 。 不一致的行為 出現溢位時的行為不一定在所有情形下一致。例如，在 Rust 語言中，雖然提供給使用者選擇和控制的功能，但數學運算子的基本使用行為自然是固定的； 但是，這種固定行為在 除錯 模式下構建的程式和 釋出 模式下構建的程式之間是不同的。在 C 中，無符號整數溢位被定義為迴繞，而有符號整數溢位導致未定義的行為。 舉例 意外的算術溢位是程式錯誤的常見原因。此類溢位錯誤可能難以發現和診斷，因為它們可能僅針對非常大的輸入資料集表現出來，而這些資料集不太可能用於驗證測試。 如在許多搜尋演算法中所做的，透過將兩個數字相加併除以二來獲取算術平均值，如果總和（儘管平均值沒有）太大而無法表示，並因此溢位，則會導致錯誤。 發動機轉向軟體中未處理的算術溢位是 1996 年阿麗亞娜 5 運載火箭首飛墜毀的主要原因。 該軟體被認為沒有錯誤，因為它已在許多以前的飛行中使用過，但那些使用過的火箭較小，產生的加速度比阿麗亞娜 5 號低。令人沮喪的是，發生溢位錯誤的軟體部分甚至不需要在導致火箭失敗時執行：這是一個較小的阿麗亞娜 5 前身的發射機制過程，當它為新火箭被改寫時，仍然保留在軟體中。此外，失敗的真正原因是軟體在檢測到溢位時如何處理溢位的工程規範中存在缺陷：它向其匯流排進行了診斷轉儲，該匯流排在開發期間的軟體測試期間本應連線到測試裝置但在飛行過程中連線到火箭轉向馬達；資料轉儲將發動機噴嘴猛烈推向一側，這使火箭失去了空氣動力學控制，並導致其在空中迅速解體。 阿麗亞娜 5 號發射失敗事故的官方報告。 2015 年 4 月 30 日，美國聯邦航空管理局宣佈將命令波音 787 操作員定期重置其電氣系統，以避免可能導致電力損失和衝壓空氣渦輪部署的整數溢位，波音在第四季度部署了軟體更新。歐洲航空安全域性於 2015 年 5 月 4 日跟進。 錯誤發生在 2³¹ 釐秒（約 249 天）後，表示一個 32 位有符號整數。 溢位錯誤在一些電腦遊戲中很明顯。在 NES 的《超級馬里奧兄弟》中，在一個有符號位元組中儲存生命數（範圍從 128 到 127），這意味著玩家可以安全地擁有 127 條生命，但是當玩家達到第 128 條生命時，會導致計數器滾動到零（儘管在此之前數字計數器出現故障）然後死亡，遊戲即時結束。這是由資料溢位引起的，因為開發人員可能沒有想到可以贏得上述數量的生命。在街機遊戲《大金剛》中，由於時間 獎勵的整數溢位，不可能超過 22 級。遊戲將使用者所在的級別數乘以 10 再加上 40。當他們達到 22 級時，時間 獎勵數為 260，這對於其 8 位 256 值暫存器來說太大了，因此它會自行重置到 0 並給出剩餘的 4 作為時間 獎勵 太短而無法完成關卡。在《小金剛算數》中，當試圖計算一個超過 10000 的數字時，它只顯示前 4 位數字。溢位是《吃豆人》中著名的 分屏 關卡的原因。《文明》中臭名昭著的漏洞據稱是由整數下溢引起的，當遊戲試圖從甘地的預設攻擊等級 1 中減去 2 時，將其設定為 255，比正常最大值 10 高出近 26 倍。（席德梅爾在一次採訪中聲稱這實際上是故意的。）這樣的錯誤也導致了從 Infdev 開發階段到 Beta 173 存在的我的世界中的邊境之地；它後來在 Beta 18 中得到修復，但仍然存在於 Minecraft 袖珍版和 Windows 10 版中。在超級任天堂娛樂系統 NES 遊戲中，玩家可以透過在支付比賽費用後被罰款超過剩餘金額的限制，從而導致他們在比賽中的金額低於 0 美元，這會導致整數出現故障。並給予玩家 65535000 美元，比它在負數後的收益多出 65535000 美元。Archived at Ghostarchive and the Wayback Machine 在潛行者：晴空中也發生了類似的故障，玩家可以在沒有足夠資金的情況下透過快速旅行而陷入負數，然後繼續進行玩家被搶劫並拿走所有貨幣的事件。在遊戲試圖將玩家的錢帶走直到 0 美元后，玩家將獲得 2147482963 遊戲幣。 IBMMicrosoft 宏彙編器 MASM 版本 100，以及可能由同一 Pascal 編譯器構建的所有其他程式，在堆疊設定程式碼中存在整數溢位和符號錯誤，這會阻止它們在較新的常見的具有超過 512 KB 記憶體配置的 DOS 機器或模擬器上執行。 程式掛起或顯示錯誤訊息，並退出到 DOS。 2016 年 8 月， 賭場的一臺賭場機器因溢位錯誤而打印出 4294967276 美元的獎券。 賭場拒絕支付這筆款項，稱其為故障，在他們的辯護中用了機器明確表示最高支付為 10000 美元，因此任何超過該金額的獎金都必須是程式設計錯誤的結果。 紐約州博彩委員會作出有利於賭場的裁決。 參考文獻 Category 計算機算術 Category 保全漏洞 Category 程式錯誤