pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

檢測 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.

我發現雖然檢測無符號整數溢出非常簡單,但檢測 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)會優化掉上面的在設置優化標志時檢查,因為編譯器假定不可能發生有符號溢出.這完全打破了檢查溢出的嘗試.

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;
}

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

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.

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

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) 不會為編譯器提供優化溢出檢查的機會?我在想可能有某種方法可以通過將兩個操作數強制轉換為無符號,并通過滾動您自己的二進制補碼算法來執行檢查,但我不確定如何做到這一點.

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.

推薦答案

您的減法方法是正確且明確的.編譯器無法優化它.

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

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

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 大小的加法和單個條件跳轉溢出,并且永遠不會實際執行更大的加法.

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(創建 DLL 時導出所有符號)
Getting started with OpenCV 2.4 and MinGW on Windows 7(Windows 7 上的 OpenCV 2.4 和 MinGW 入門)
主站蜘蛛池模板: 水质监测站_水质在线分析仪_水质自动监测系统_多参数水质在线监测仪_水质传感器-山东万象环境科技有限公司 | 布袋式除尘器|木工除尘器|螺旋输送机|斗式提升机|刮板输送机|除尘器配件-泊头市德佳环保设备 | 伺服电机维修、驱动器维修「安川|三菱|松下」伺服维修公司-深圳华创益 | 云南标线|昆明划线|道路标线|交通标线-就选云南云路施工公司-云南云路科技有限公司 | 粘弹体防腐胶带,聚丙烯防腐胶带-全民塑胶 | 步进_伺服_行星减速机,微型直流电机,大功率直流电机-淄博冠意传动机械 | 浙江筋膜枪-按摩仪厂家-制造商-肩颈按摩仪哪家好-温州市合喜电子科技有限公司 | 特种电缆厂家-硅橡胶耐高温电缆-耐低温补偿导线-安徽万邦特种电缆有限公司 | 德国进口电锅炉_商用电热水器_壁挂炉_电采暖器_电热锅炉[德国宝] | 哈希余氯测定仪,分光光度计,ph在线监测仪,浊度测定仪,试剂-上海京灿精密机械有限公司 | 南京PVC快速门厂家南京快速卷帘门_南京pvc快速门_世界500强企业国内供应商_南京美高门业 | 火锅加盟_四川成都火锅店加盟_中国火锅连锁品牌十强_朝天门火锅【官网】 | 橡胶接头|可曲挠橡胶接头|橡胶软接头安装使用教程-上海松夏官方网站 | 硫化罐-电加热蒸汽硫化罐生产厂家-山东鑫泰鑫智能装备有限公司 | 不锈钢水箱生产厂家_消防水箱生产厂家-河南联固供水设备有限公司 | 偏心半球阀-电动偏心半球阀-调流调压阀-旋球阀-上欧阀门有限公司 | 水质监测站_水质在线分析仪_水质自动监测系统_多参数水质在线监测仪_水质传感器-山东万象环境科技有限公司 | 山东成考网-山东成人高考网 | 北京环球北美考试院【官方网站】|北京托福培训班|北京托福培训 | 北京康百特科技有限公司-分子蒸馏-短程分子蒸馏设备-实验室分子蒸馏设备 | 超声波_清洗机_超声波清洗机专业生产厂家-深圳市好顺超声设备有限公司 | 铝板冲孔网,不锈钢冲孔网,圆孔冲孔网板,鳄鱼嘴-鱼眼防滑板,盾构走道板-江拓数控冲孔网厂-河北江拓丝网有限公司 | 伊卡洛斯软装首页-电动窗帘,别墅窗帘,定制窗帘,江浙沪1000+别墅窗帘案例 | 私人别墅家庭影院系统_家庭影院音响_家庭影院装修设计公司-邦牛影音 | 隔爆型防爆端子分线箱_防爆空气开关箱|依客思| 拉力测试机|材料拉伸试验机|电子拉力机价格|万能试验机厂家|苏州皖仪实验仪器有限公司 | 高中学习网-高考生信息学习必备平台 | 无水硫酸铝,硫酸铝厂家-淄博双赢新材料科技有限公司 | 东莞市海宝机械有限公司-不锈钢分选机-硅胶橡胶-生活垃圾-涡电流-静电-金属-矿石分选机 | TPE_TPE热塑性弹性体_TPE原料价格_TPE材料厂家-惠州市中塑王塑胶制品公司- 中塑王塑胶制品有限公司 | 注塑_注塑加工_注塑模具_塑胶模具_注塑加工厂家_深圳环科 | 丙烷/液氧/液氮气化器,丙烷/液氧/液氮汽化器-无锡舍勒能源科技有限公司 | 南京和瑞包装有限公司| 上海阳光泵业制造有限公司 -【官方网站】| 自动气象站_气象站监测设备_全自动气象站设备_雨量监测站-山东风途物联网 | 包塑丝_高铁绑丝_地暖绑丝_涂塑丝_塑料皮铁丝_河北创筹金属丝网制品有限公司 | 酸度计_PH计_特斯拉计-西安云仪| 安规_综合测试仪,电器安全性能综合测试仪,低压母线槽安规综合测试仪-青岛合众电子有限公司 | 数显水浴恒温振荡器-分液漏斗萃取振荡器-常州市凯航仪器有限公司 | 加气混凝土砌块设备,轻质砖设备,蒸养砖设备,新型墙体设备-河南省杜甫机械制造有限公司 | 深圳高新投三江工业消防解决方案提供厂家_服务商_园区智慧消防_储能消防解决方案服务商_高新投三江 |