Library Documentation Index

Safe Numerics

PrevUpHomeNext

Arithmetic on Unsigned Integers Can Yield Incorrect Results

Subtracting two unsigned values of the same size will result in an unsigned value. If the first operand is less than the second the result will be arithmetically in correct. But if the size of the unsigned types is less than that of an unsigned int, C/C++ will promote the types to signed int before subtracting resulting in an correct result. In either case, there is no indication of an error. Somehow, the programmer is expected to avoid this behavior. Advice usually takes the form of "Don't use unsigned integers for arithmetic". This is well and good, but often not practical. C/C++ itself uses unsigned for sizeof(T) which is then used by users in arithmetic.

This program demonstrates this problem. The solution is to replace instances of built in integer types with corresponding safe types.

// Copyright (c) 2018 Robert Ramey // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include <iostream> #include <boost/safe_numerics/safe_integer.hpp> int main(int, const char *[]){ std::cout << "example 8:"; std::cout << "undetected erroneous expression evaluation" << std::endl; std::cout << "Not using safe numerics" << std::endl; try{ unsigned int x = 127; unsigned int y = 2; unsigned int z; // this produces an invalid result ! z = y - x; std::cout << "error NOT detected!" << std::endl; std::cout << z << " != " << y << " - " << x << std::endl; } catch(const std::exception &){ std::cout << "error detected!" << std::endl; } // solution: replace int with safe<int> std::cout << "Using safe numerics" << std::endl; try{ using namespace boost::safe_numerics; safe<unsigned int> x = 127; safe<unsigned int> y = 2; safe<unsigned int> z; // rather than producing an invalid result an exception is thrown z = y - x; std::cout << "error NOT detected!" << std::endl; std::cout << z << " != " << y << " - " << x << std::endl; } catch(const std::exception & e){ // which we can catch here std::cout << "error detected:" << e.what() << std::endl; } return 0; }

example 8:undetected erroneous expression evaluation
Not using safe numerics
error NOT detected!
4294967171 != 2 - 127
Using safe numerics
error detected:subtraction result cannot be negative: negative overflow error
Program ended with exit code: 0

PrevUpHomeNext