Question

What is the single most effective practice to prevent arithmetic overflow and underflow?

Some examples that come to mind are:

  • testing based on valid input ranges
  • validation using formal methods
  • use of invariants
  • detection at runtime using language features or libraries (this does not prevent it)
Was it helpful?

Solution

One possibility is to use a language that has arbitrarily sized integers that never overflow / underflow.

Otherwise, if this is something you're really concerned about, and if your language allows it, write a wrapper class that acts like an integer, but checks every operation for overflow. You could even have it do the check on debug builds, and leave things optimized for release builds. In a language like C++, you could do this, and it would behave almost exactly like an integer for release builds, but for debug builds you'd get full run-time checking.

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

Edit:

Turns out someone is doing this already for C++ - the current implementation is focused for Visual Studio, but it looks like they're getting support for gcc as well.

OTHER TIPS

I write a lot of test code to do range/validity checking on my code. This tends to catch most of these types of situations - and definitely helps me write more bulletproof code.

Use high precision floating point numbers like a long double.

I think you are missing one very important option in your list: choose the right programming language for the job. There are many programming languages which do not have these problems, because they don't have fixed size integers.

There are more important considerations when choosing which language you use than the size of the integer. Simply check your input if you don't know if the value is in bounds, or use exception handling if the case is extremely rare.

A wrapper that checks for inconsistencies will make sense in many cases. If an additive operation (ie, addition or multiplication) on two or more integers results in a smaller value than the operands then you know something went wrong. Every additive operation should be followed by,

if (sum < operand1 || sum < operand2)
    omg_error();

Likewise any operation that should logically result in a smaller value should be check to see if it was accidentally embiggin'd.

Have you investigated the use of formal methods to check your code to prove that it is free of overflows? A formal methods technique known as abstract interpretation can check the robustness of your software to prove that your software will not suffer from an overflow, underflow, divide by zero, overflow, or other similar run-time error. It is a mathematical technique that exhaustively analyzes your software. The technique was pioneered by Patrick Cousot in the 1970s. It was successfully used to diagnose an overflow condition in the Arian 5 rocket where an overflow caused the destruction of the launch vehicle. The overflow was caused while converting a floating point number to an integer. You can find more information about this technique here and also on Wikipedia.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top