Integer Overflow

今天做了一個實驗,就是對一些數據的邊界進行測試,結果竟然拋異常終止了。


這有點出乎我的意料,因爲並不是除0錯,我以爲會忽略溢出呢。後來看了資料,才明白是怎麼回事。


首先,32bit整數的表達範圍是 -2147483648 ~ 2147483647,我們可以看到INT_MIN的定義是( - 2147483647 - 1 ),據《深入理解計算機系統》裏面講述,這是因爲將一個字符串解析成數字,如果是這樣:


int parse_int( char* str ) {
    int  sign = 0, ans = 0;
    if( *str == '-' ) { ++str; sign = 1; }
    while( '0' <= *str && *str <= '9' ) {
        ans = ans * 10 + *str++ - '0';
    }
    return  sign ? -ans : ans;
}

那麼就會導致ans在計算2147483648的時候溢出(因爲ans無法保存2147483648),那麼再取反也是不對的。我不知道當前主流編譯器是不是用這麼弱的方法解析(因爲既然scanf和cin都沒有問題,顯然編譯器也可以採用同樣的方法),可能這麼寫是爲了兼容古老的編譯器吧。


但是我們也知道,有一些加減法或乘法溢出,是不會報錯的,甚至我們還利用了這個特點做一些運算。但是今天我遇到了一個除法出錯的情況。

int  x, y;
std::cin >> x >> y;
std::cout << (x / y) << std::endl;

如果輸入x = -2147483648  y = -1就會出錯,在VS2012中彈出“unhandled exception xxx Integer Overflow”,在GCC中更可惡,提示“浮點數異常”,如果我的測試代碼包含了浮點數運算,那我肯定只檢查浮點數那裏了,這個一定要注意!!!


實際上,C語言中,對於有符號整型運算的溢出是未定義的行爲,而無符號整數則將溢出的部分捨去,取結果的低位部分作爲結果。(In the C programming language, signed integer overflow causes undefined behavior, while unsigned integer overflow causes the number to be reduced modulo a power of two, meaning that unsigned integers "wrap around" on overflow.


另外就是Linux中的信號有一個是SIGFPE,當執行算術運算出錯時拋出,例如除0錯。看字面意思是Floating-Point Error纔對,可是整型確實也用到了它。

SIGFPE The SIGFPE signal is sent to a process when it executes an erroneous arithmetic operation, such as division by zero.


參考資料:

http://en.wikipedia.org/wiki/Integer_overflow

http://en.wikipedia.org/wiki/SIGFPE#SIGFPE




發佈了99 篇原創文章 · 獲贊 98 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章