...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Safe Numerics |
When some operation on signed integer types results in a result which exceeds the capacity of a data variable to hold it, the result is undefined. In the case of unsigned integer types a similar situation results in a value wrap as per modulo arithmetic. In either case the result is different than in integer number arithmetic in the mathematical sense. This is called "overflow". Since word size can differ between machines, code which produces mathematically correct results in one set of circumstances may fail when re-compiled on a machine with different hardware. When this occurs, most C++ programs will continue to execute with no indication that the results are wrong. It is the programmer's responsibility to ensure such undefined behavior is avoided.
This program demonstrates this problem. The solution is to replace instances of built in integer types with corresponding safe types.
#include <cassert> #include <exception> #include <iostream> #include <cstdint> #include <boost/safe_numerics/safe_integer.hpp> int main(int, const char *[]){ std::cout << "example 1:"; std::cout << "undetected erroneous expression evaluation" << std::endl; std::cout << "Not using safe numerics" << std::endl; try{ std::int8_t x = 127; std::int8_t y = 2; std::int8_t z; // this produces an invalid result ! z = x + y; std::cout << "error NOT detected!" << std::endl; std::cout << (int)z << " != " << (int)x << " + " << (int)y << std::endl; } catch(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<std::int8_t> x = INT_MAX; safe<std::int8_t> y = 2; safe<std::int8_t> z; // rather than producing an invalid result an exception is thrown z = x + y; } catch(std::exception & e){ // which we can catch here std::cout << "error detected:" << e.what() << std::endl; } return 0; }
example 1:undetected erroneous expression evaluation Not using safe numerics error NOT detected! -127 != 127 + 2 Using safe numerics error detected:converted signed value too large: positive overflow error Program ended with exit code: 0