防止算术上溢和下溢的单一最有效实践
时间:2020-03-05 18:57:39 来源:igfitidea点击:
防止算术上溢和下溢的最有效的实践方法是什么?
我想到的一些例子是:
- 根据有效输入范围进行测试
- 使用形式化方法进行验证
- 不变量的使用
- 使用语言功能或者库在运行时进行检测(这不会阻止它)
解决方案
回答
一种可能性是使用一种具有任意大小的整数的语言,该整数从不上溢/下溢。
否则,如果这是我们真正关心的事情,并且如果语言允许,请编写一个包装器类,其作用类似于整数,但检查每个操作是否溢出。我们甚至可以让它对调试版本进行检查,并为发布版本进行优化。在像C ++这样的语言中,我们可以执行此操作,并且它的行为几乎与发行版本的整数一样,但是对于调试版本,我们将获得完整的运行时检查。
class CheckedInt { private: int Value; public: // Constructor CheckedInt(int src) : Value(src) {} // Conversions back to int operator int&() { return Value; } operator const int &() const { return Value; } // Operators CheckedInt operator+(CheckedInt rhs) const { if (rhs.Value < 0 && rhs.Value + Value > Value) throw OverflowException(); if (rhs.Value > 0 && rhs.Value + Value < Value) throw OverflowException(); return CheckedInt(rhs.Value + Value); } // Lots more operators... };
编辑:
事实证明有人已经针对C ++进行了此操作,当前实现主要针对Visual Studio,但看起来他们也正在获得对gcc的支持。
回答
我编写了很多测试代码来对代码进行范围/有效性检查。这往往会遇到大多数此类情况,并且绝对可以帮助我编写更多的防弹代码。
回答
使用高精度浮点数,例如长双精度数。
回答
我认为我们在列表中缺少一个非常重要的选择:为工作选择正确的编程语言。许多编程语言都没有这些问题,因为它们没有固定大小的整数。
回答
选择使用哪种语言时,还有比整数大小更重要的考虑因素。如果我们不知道该值是否在范围内,则只需检查输入即可;如果这种情况极为罕见,则可以使用异常处理。
回答
在许多情况下,检查不一致的包装器是有意义的。如果对两个或者多个整数进行加法运算(即加法或者乘法)导致值小于操作数,那么我们就知道出了点问题。每个加法运算之后,
if (sum < operand1 || sum < operand2) omg_error();
同样,应该检查在逻辑上应导致较小值的任何操作,以查看是否意外插入了该操作。