1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> 4<title>Implicit Conversions Can Lead to Erroneous Results</title> 5<link rel="stylesheet" href="../boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../index.html" title="Safe Numerics"> 8<link rel="up" href="../tutorial.html" title="Tutorial and Motivating Examples"> 9<link rel="prev" href="3.html" title="Arithmetic on Unsigned Integers Can Yield Incorrect Results"> 10<link rel="next" href="5.html" title="Mixing Data Types Can Create Subtle Errors"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img href="index.html" height="164px" src="pre-boost.jpg" alt="Library Documentation Index"></td> 15<td><h2>Safe Numerics</h2></td> 16</tr></table> 17<div class="spirit-nav"> 18<a accesskey="p" href="3.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="5.html"><img src="../images/next.png" alt="Next"></a> 19</div> 20<div class="section"> 21<div class="titlepage"><div><div><h3 class="title"> 22<a name="safe_numerics.tutorial.4"></a>Implicit Conversions Can Lead to Erroneous Results</h3></div></div></div> 23<p>At CPPCon 2016 Jon Kalb gave a very entertaining (and disturbing) 24 <a href="https://www.youtube.com/watch?v=wvtFGa6XJDU" target="_top">lightning 25 talk</a> related to C++ expressions.</p> 26<p>The talk included a very, very simple example similar to the 27 following:</p> 28<pre class="programlisting"><span class="comment">// Copyright (c) 2018Robert Ramey</span> 29<span class="comment">//</span> 30<span class="comment">// Distributed under the Boost Software License, Version 1.0. (See</span> 31<span class="comment">// accompanying file LICENSE_1_0.txt or copy at</span> 32<span class="comment">// http://www.boost.org/LICENSE_1_0.txt)</span> 33 34<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span> 35 36<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> 37 38<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="special">)</span><span class="special">{</span> 39 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"example 4: "</span><span class="special">;</span> 40 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"implicit conversions change data values"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 41 <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> 42 43 <span class="comment">// problem: implicit conversions change data values</span> 44 <span class="keyword">try</span><span class="special">{</span> 45 <span class="keyword">signed</span> <span class="keyword">int</span> <span class="identifier">a</span><span class="special">{</span><span class="special">-</span><span class="number">1</span><span class="special">}</span><span class="special">;</span> 46 <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">{</span><span class="number">1</span><span class="special">}</span><span class="special">;</span> 47 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a is "</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="string">" b is "</span> <span class="special"><<</span> <span class="identifier">b</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">;</span> 48 <span class="keyword">if</span><span class="special">(</span><span class="identifier">a</span> <span class="special"><</span> <span class="identifier">b</span><span class="special">)</span><span class="special">{</span> 49 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a is less than b\n"</span><span class="special">;</span> 50 <span class="special">}</span> 51 <span class="keyword">else</span><span class="special">{</span> 52 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"b is less than a\n"</span><span class="special">;</span> 53 <span class="special">}</span> 54 <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> 55 <span class="special">}</span> 56 <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> 57 <span class="comment">// never arrive here - just produce the wrong answer!</span> 58 <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> 59 <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span> 60 <span class="special">}</span> 61 62 <span class="comment">// solution: replace int with safe<int> and unsigned int with safe<unsigned int></span> 63 <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> 64 <span class="keyword">try</span><span class="special">{</span> 65 <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> 66 <span class="identifier">safe</span><span class="special"><</span><span class="keyword">signed</span> <span class="keyword">int</span><span class="special">></span> <span class="identifier">a</span><span class="special">{</span><span class="special">-</span><span class="number">1</span><span class="special">}</span><span class="special">;</span> 67 <span class="identifier">safe</span><span class="special"><</span><span class="keyword">unsigned</span> <span class="keyword">int</span><span class="special">></span> <span class="identifier">b</span><span class="special">{</span><span class="number">1</span><span class="special">}</span><span class="special">;</span> 68 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a is "</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="string">" b is "</span> <span class="special"><<</span> <span class="identifier">b</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">;</span> 69 <span class="keyword">if</span><span class="special">(</span><span class="identifier">a</span> <span class="special"><</span> <span class="identifier">b</span><span class="special">)</span><span class="special">{</span> 70 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"a is less than b\n"</span><span class="special">;</span> 71 <span class="special">}</span> 72 <span class="keyword">else</span><span class="special">{</span> 73 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"b is less than a\n"</span><span class="special">;</span> 74 <span class="special">}</span> 75 <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> 76 <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span> 77 <span class="special">}</span> 78 <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> 79 <span class="comment">// never arrive here - just produce the correct answer!</span> 80 <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> 81 <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> 82 <span class="special">}</span> 83 <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> 84<span class="special">}</span> 85</pre> 86<pre class="screen">example 3: implicit conversions change data values 87Not using safe numerics 88a is -1 b is 1 89b is less than a 90error NOT detected! 91Using safe numerics 92a is -1 b is 1 93converted negative value to unsigned: domain error 94error detected! 95</pre> 96<p>A normal person reads the above code and has to be dumbfounded by 97 this. The code doesn't do what the text - according to the rules of 98 algebra - says it does. But C++ doesn't follow the rules of algebra - it 99 has its own rules. There is generally no compile time error. You can get a 100 compile time warning if you set some specific compile time switches. The 101 explanation lies in reviewing how C++ reconciles binary expressions 102 (<code class="computeroutput">a < b</code> is an expression here) where operands are different 103 types. In processing this expression, the compiler:</p> 104<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 105<li class="listitem"><p>Determines the "best" common type for the two operands. In 106 this case, application of the rules in the C++ standard dictate that 107 this type will be an <code class="computeroutput">unsigned int</code>.</p></li> 108<li class="listitem"><p>Converts each operand to this common type. The signed value of 109 -1 is converted to an unsigned value with the same bit-wise 110 contents, 0xFFFFFFFF, on a machine with 32 bit integers. This 111 corresponds to a decimal value of 4294967295.</p></li> 112<li class="listitem"><p>Performs the calculation - in this case it's 113 <code class="computeroutput"><</code>, the "less than" operation. Since 1 is less than 114 4294967295 the program prints "b is less than a".</p></li> 115</ul></div> 116<p>In order for a programmer to detect and understand this error he 117 should be pretty familiar with the implicit conversion rules of the C++ 118 standard. These are available in a copy of the standard and also in the 119 canonical reference book <em class="citetitle"><a class="link" href="bibliography.html#stroustrup" title="The C++ Programming Language">The C++ 120 Programming Language</a></em> (both are over 1200 pages long!). 121 Even experienced programmers won't spot this issue and know to take 122 precautions to avoid it. And this is a relatively easy one to spot. In the 123 more general case this will use integers which don't correspond to easily 124 recognizable numbers and/or will be buried as a part of some more complex 125 expression.</p> 126<p>This example generated a good amount of web traffic along with 127 everyone's pet suggestions. See for example <a href="https://bulldozer00.com/2016/10/16/the-unsigned-conundrum/" target="_top">a blog 128 post with everyone's favorite "solution"</a>. All the proposed 129 "solutions" have disadvantages and attempts to agree on how handle this 130 are ultimately fruitless in spite of, or maybe because of, the <a href="https://twitter.com/robertramey1/status/795742870045016065" target="_top">emotional 131 content</a>. Our solution is by far the simplest: just use the safe 132 numerics library as shown in the example above.</p> 133<p>Note that in this particular case, usage of the safe types results 134 in no runtime overhead in using the safe integer library. Code generated 135 will either equal or exceed the efficiency of using primitive integer 136 types.</p> 137</div> 138<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 139<td align="left"></td> 140<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 141 Software License</a></p> 142</div></td> 143</tr></table> 144<hr> 145<div class="spirit-nav"> 146<a accesskey="p" href="3.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="5.html"><img src="../images/next.png" alt="Next"></a> 147</div> 148</body> 149</html> 150