mirror of
https://github.com/boostorg/safe_numerics.git
synced 2026-02-22 15:42:30 +00:00
improved TOC and chunking. This is complicated by the fact we that we desire different depths. put copies of boost logo in subdirectories
94 lines
11 KiB
HTML
94 lines
11 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
|
<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.76.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 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.</p>
|
|
<p>This program demonstrates this problem. The solution is to replace
|
|
instances of <code class="computeroutput">char</code> type with <code class="computeroutput">safe<char></code>
|
|
type.</p>
|
|
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span>
|
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">exception</span><span class="special">></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">cstdint</span><span class="special">></span>
|
|
|
|
<span class="preprocessor">#include</span> <span class="string">"../include/safe_integer.hpp"</span>
|
|
|
|
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span> <span class="identifier">argv</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="comment">// problem: arithmetic operations can yield incorrect results.</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="comment">// but assert fails to detect it since C++ implicitly</span>
|
|
<span class="comment">// converts variables to int before evaluating he expression!</span>
|
|
<span class="comment">// assert(z == x + y);</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span><span class="special">(</span><span class="identifier">z</span><span class="special">)</span> <span class="special"><<</span> <span class="string">" != "</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">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">"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="special">}</span>
|
|
<span class="keyword">catch</span><span class="special">(</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="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 std::int8_t with safe<std::int8_t></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">numeric</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="number">127</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 and 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="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 can catch here</span>
|
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</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>
|
|
<p>Note that I've used <code class="computeroutput">char</code> types in this example to make
|
|
the problem and solution easier to see. The exact same example could have
|
|
been done with <code class="computeroutput">int</code> types albeit with different values.</p>
|
|
</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 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>
|