mirror of
https://github.com/boostorg/safe_numerics.git
synced 2026-01-24 06:22:08 +00:00
a) Updated CMake files to run tests and properly import other boost dependencies b) Improved custom expectation facility and added test for same c) fixed error when checking wasn’t being done on assignment d) fixed error where lower bound was assumed to be 0
99 lines
12 KiB
HTML
99 lines
12 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<title>Arithmetic Expressions Can Yield Incorrect Results</title>
|
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
|
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
|
<link rel="home" href="../index.html" title="Safe Numerics">
|
|
<link rel="up" href="../tutorial.html" title="Tutorial and Motivating Examples">
|
|
<link rel="prev" href="../tutorial.html" title="Tutorial and Motivating Examples">
|
|
<link rel="next" href="2.html" title="Arithmetic Operations Can Overflow Silently">
|
|
</head>
|
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
|
<table cellpadding="2" width="100%"><tr>
|
|
<td valign="top"><img href="index.html" height="164px" src="pre-boost.jpg" alt="Library Documentation Index"></td>
|
|
<td><h2>Safe Numerics</h2></td>
|
|
</tr></table>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="../tutorial.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="2.html"><img src="../images/next.png" alt="Next"></a>
|
|
</div>
|
|
<div class="section">
|
|
<div class="titlepage"><div><div><h3 class="title">
|
|
<a name="safe_numerics.tutorial.1"></a>Arithmetic Expressions Can Yield Incorrect Results</h3></div></div></div>
|
|
<p>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.</p>
|
|
<p>This program demonstrates this problem. The solution is to replace
|
|
instances of built in integer types with corresponding safe types.</p>
|
|
<pre class="programlisting"><span class="comment">// Copyright (c) 2018 Robert Ramey</span>
|
|
<span class="comment">//</span>
|
|
<span class="comment">// Distributed under the Boost Software License, Version 1.0. (See</span>
|
|
<span class="comment">// accompanying file LICENSE_1_0.txt or copy at</span>
|
|
<span class="comment">// http://www.boost.org/LICENSE_1_0.txt)</span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">safe_numerics</span><span class="special">/</span><span class="identifier">safe_integer</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="special">[</span><span class="special">]</span><span class="special">)</span><span class="special">{</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"example 1:"</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"undetected erroneous expression evaluation"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Not using safe numerics"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="keyword">try</span><span class="special">{</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">127</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span> <span class="identifier">y</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span> <span class="identifier">z</span><span class="special">;</span>
|
|
<span class="comment">// this produces an invalid result !</span>
|
|
<span class="identifier">z</span> <span class="special">=</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"error NOT detected!"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="special">(</span><span class="keyword">int</span><span class="special">)</span><span class="identifier">z</span> <span class="special"><<</span> <span class="string">" != "</span> <span class="special"><<</span> <span class="special">(</span><span class="keyword">int</span><span class="special">)</span><span class="identifier">x</span> <span class="special"><<</span> <span class="string">" + "</span> <span class="special"><<</span> <span class="special">(</span><span class="keyword">int</span><span class="special">)</span><span class="identifier">y</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="special">&</span><span class="special">)</span><span class="special">{</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"error detected!"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="comment">// solution: replace int with safe<int></span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"Using safe numerics"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="keyword">try</span><span class="special">{</span>
|
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">safe_numerics</span><span class="special">;</span>
|
|
<span class="identifier">safe</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span><span class="special">></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">INT_MAX</span><span class="special">;</span>
|
|
<span class="identifier">safe</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span><span class="special">></span> <span class="identifier">y</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span>
|
|
<span class="identifier">safe</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">int8_t</span><span class="special">></span> <span class="identifier">z</span><span class="special">;</span>
|
|
<span class="comment">// rather than producing an invalid result an exception is thrown</span>
|
|
<span class="identifier">z</span> <span class="special">=</span> <span class="identifier">x</span> <span class="special">+</span> <span class="identifier">y</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exception</span> <span class="special">&</span> <span class="identifier">e</span><span class="special">)</span><span class="special">{</span>
|
|
<span class="comment">// which we can catch here</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"error detected:"</span> <span class="special"><<</span> <span class="identifier">e</span><span class="special">.</span><span class="identifier">what</span><span class="special">(</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
|
<span class="special">}</span>
|
|
</pre>
|
|
<pre class="screen">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</pre>
|
|
</div>
|
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
|
<td align="left"></td>
|
|
<td align="right"><div class="copyright-footer">Copyright © 2012-2018 Robert Ramey<p><a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">Subject to Boost
|
|
Software License</a></p>
|
|
</div></td>
|
|
</tr></table>
|
|
<hr>
|
|
<div class="spirit-nav">
|
|
<a accesskey="p" href="../tutorial.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../tutorial.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="2.html"><img src="../images/next.png" alt="Next"></a>
|
|
</div>
|
|
</body>
|
|
</html>
|