![]() |
Safe Numerics |
When some operation results in a result which exceeds the capacity of a data variable to hold it, the result is undefined. This is called "overflow". Since word size can differ between machines, code which produces correct results in one set of circumstances may fail when re-compiled on a machine with different hardware. When this occurs, Most C++ compilers 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 char type with safe<char>
type.
#include <cassert>
#include <exception>
#include <iostream>
#include <cstdint>
#include "../include/safe_integer.hpp"
int main(int argc, const char * argv[]){
std::cout << "example 1:";
std::cout << "undetected erroneous expression evaluation" << std::endl;
std::cout << "Not using safe numerics" << std::endl;
// problem: arithmetic operations can yield incorrect results.
try{
std::int8_t x = 127;
std::int8_t y = 2;
std::int8_t z;
// this produces an invalid result !
z = x + y;
// but assert fails to detect it since C++ implicitly
// converts variables to int before evaluating he expression!
// assert(z == x + y);
std::cout << static_cast<int>(z) << " != " << x + y << std::endl;
std::cout << "error NOT detected!" << std::endl;
}
catch(std::exception){
std::cout << "error detected!" << std::endl;
}
// solution: replace std::int8_t with safe<std::int8_t>
std::cout << "Using safe numerics" << std::endl;
try{
using namespace boost::numeric;
safe<std::int8_t> x = 127;
safe<std::int8_t> y = 2;
safe<std::int8_t> z;
// rather than producing and invalid result an exception is thrown
z = x + y;
}
catch(std::exception & e){
// which can catch here
std::cout << e.what() << std::endl;
}
return 0;
}
Note that I've used char types in this example to make
the problem and solution easier to see. The exact same example could have
been done with int types albeit with different values.