久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

檢測 C/C++ 中的有符號溢出

Detecting signed overflow in C/C++(檢測 C/C++ 中的有符號溢出)
本文介紹了檢測 C/C++ 中的有符號溢出的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

乍一看,這個問題似乎是 How檢測整數溢出?,但實際上有很大不同.

At first glance, this question may seem like a duplicate of How to detect integer overflow?, however it is actually significantly different.

我發(fā)現雖然檢測無符號整數溢出非常簡單,但檢測 C/C++ 中的有符號溢出實際上比大多數人想象的要困難.

I've found that while detecting an unsigned integer overflow is pretty trivial, detecting a signed overflow in C/C++ is actually more difficult than most people think.

最明顯但最幼稚的方法是:

The most obvious, yet naive, way to do it would be something like:

int add(int lhs, int rhs)
{
 int sum = lhs + rhs;
 if ((lhs >= 0 && sum < rhs) || (lhs < 0 && sum > rhs)) {
  /* an overflow has occurred */
  abort();
 }
 return sum; 
}

這樣做的問題是,根據 C 標準,有符號整數溢出是未定義的行為. 換句話說,根據標準,一旦您甚至導致有符號溢出,您的程序就像取消引用空指針一樣無效.所以你不能導致未定義的行為,然后在事后嘗試檢測溢出,如上面的后置條件檢查示例.

The problem with this is that according to the C standard, signed integer overflow is undefined behavior. In other words, according to the standard, as soon as you even cause a signed overflow, your program is just as invalid as if you dereferenced a null pointer. So you can't cause undefined behavior, and then try to detect the overflow after the fact, as in the above post-condition check example.

盡管上述檢查可能適用于許多編譯器,但您不能指望它.事實上,因為 C 標準說有符號整數溢出是未定義的,一些編譯器(比如 GCC)會優(yōu)化掉上面的在設置優(yōu)化標志時檢查,因為編譯器假定不可能發(fā)生有符號溢出.這完全打破了檢查溢出的嘗試.

Even though the above check is likely to work on many compilers, you can't count on it. In fact, because the C standard says signed integer overflow is undefined, some compilers (like GCC) will optimize away the above check when optimization flags are set, because the compiler assumes a signed overflow is impossible. This totally breaks the attempt to check for overflow.

因此,檢查溢出的另一種可能方法是:

So, another possible way to check for overflow would be:

int add(int lhs, int rhs)
{
 if (lhs >= 0 && rhs >= 0) {
  if (INT_MAX - lhs <= rhs) {
   /* overflow has occurred */
   abort();
  }
 }
 else if (lhs < 0 && rhs < 0) {
  if (lhs <= INT_MIN - rhs) {
   /* overflow has occurred */
   abort();
  }
 }

 return lhs + rhs;
}

這看起來更有希望,因為我們實際上不會將兩個整數相加,直到我們提前確保執(zhí)行這樣的相加不會導致溢出.因此,我們不會導致任何未定義的行為.

This seems more promising, since we don't actually add the two integers together until we make sure in advance that performing such an add will not result in overflow. Thus, we don't cause any undefined behavior.

然而,不幸的是,此解決方案的效率遠低于初始解決方案,因為您必須執(zhí)行減法運算才能測試加法運算是否有效.即使你不關心這個(小的)性能損失,我仍然不完全相信這個解決方案是足夠的.表達式 lhs <= INT_MIN - rhs 似乎與編譯器可能優(yōu)化掉的那種表達式完全一樣,認為有符號溢出是不可能的.

However, this solution is unfortunately a lot less efficient than the initial solution, since you have to perform a subtract operation just to test if your addition operation will work. And even if you don't care about this (small) performance hit, I'm still not entirely convinced this solution is adequate. The expression lhs <= INT_MIN - rhs seems exactly like the sort of expression the compiler might optimize away, thinking that signed overflow is impossible.

那么這里有更好的解決方案嗎?保證 1) 不會導致未定義行為,以及 2) 不會為編譯器提供優(yōu)化溢出檢查的機會?我在想可能有某種方法可以通過將兩個操作數強制轉換為無符號,并通過滾動您自己的二進制補碼算法來執(zhí)行檢查,但我不確定如何做到這一點.

So is there a better solution here? Something that is guaranteed to 1) not cause undefined behavior, and 2) not provide the compiler with an opportunity to optimize away overflow checks? I was thinking there might be some way to do it by casting both operands to unsigned, and performing checks by rolling your own two's-complement arithmetic, but I'm not really sure how to do that.

推薦答案

您的減法方法是正確且明確的.編譯器無法優(yōu)化它.

Your approach with subtraction is correct and well-defined. A compiler cannot optimize it away.

另一種正確的方法,如果您有更大的整數類型可用,則在較大的類型中執(zhí)行算術,然后在將其轉換回來時檢查結果是否適合較小的類型

Another correct approach, if you have a larger integer type available, is to perform the arithmetic in the larger type and then check that the result fits in the smaller type when converting it back

int sum(int a, int b)
{
    long long c;
    assert(LLONG_MAX>INT_MAX);
    c = (long long)a + b;
    if (c < INT_MIN || c > INT_MAX) abort();
    return c;
}

好的編譯器應該將整個加法和 if 語句轉換為 int 大小的加法和單個條件跳轉溢出,并且永遠不會實際執(zhí)行更大的加法.

A good compiler should convert the entire addition and if statement into an int-sized addition and a single conditional jump-on-overflow and never actually perform the larger addition.

正如斯蒂芬指出的那樣,我在使用(不太好的)編譯器 gcc 來生成正常的 asm 時遇到了麻煩.它生成的代碼并不是很慢,但肯定不是最理想的.如果有人知道此代碼的變體可以讓 gcc 做正確的事情,我很樂意看到它們.

As Stephen pointed out, I'm having trouble getting a (not-so-good) compiler, gcc, to generate the sane asm. The code it generates is not terribly slow, but certainly suboptimal. If anyone knows variants on this code that will get gcc to do the right thing, I'd love to see them.

這篇關于檢測 C/C++ 中的有符號溢出的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

boost_1_60_0 .zip installation in windows(Windows 中的 boost_1_60_0 .zip 安裝)
How do I get console output in C++ with a Windows program?(如何使用 Windows 程序在 C++ 中獲得控制臺輸出?)
How do I calculate the week number given a date?(如何計算給定日期的周數?)
OpenCV with Network Cameras(帶有網絡攝像機的 OpenCV)
Export all symbols when creating a DLL(創(chuàng)建 DLL 時導出所有符號)
Getting started with OpenCV 2.4 and MinGW on Windows 7(Windows 7 上的 OpenCV 2.4 和 MinGW 入門)
主站蜘蛛池模板: 久久大香 | 男人久久天堂 | 欧洲亚洲精品久久久久 | 免费网站国产 | 欧美日韩不卡合集视频 | 精品二三区 | 久久鲁视频| 一区二区三区中文字幕 | 视频一二三区 | 91久久精品日日躁夜夜躁欧美 | 日本激情视频在线播放 | 欧美三级成人理伦 | 亚洲精品一区二区三区蜜桃久 | 日韩精品免费 | 亚洲乱码一区二区三区在线观看 | 亚洲精品在线免费播放 | 欧美v日韩 | 成人欧美一区二区三区黑人孕妇 | 亚洲视频免费在线 | 国产亚洲成av人片在线观看桃 | www.久久久.com| 精品欧美激情精品一区 | 91电影在线播放 | 久久国产亚洲 | 毛片韩国 | 91视频电影 | 黄色一级大片在线免费看产 | 国产乱码精品一区二区三区五月婷 | 91av视频在线免费观看 | 精品久久久久国产免费第一页 | 国产精品成人国产乱一区 | 99久久99 | gav成人免费播放视频 | 国产精品久久国产精品久久 | 亚洲不卡在线观看 | 成人a视频在线观看 | 久久国 | 亚洲欧美日韩一区二区 | 伊人久久大香线 | 久久精品视频91 | 91久久精品一区二区二区 |