Files
safe_numerics/doc/boostbook/tutorial.xml
Robert Ramey 63dd89210e Enabled Boost Book syntax highlighting
improved TOC and chunking.  This is complicated by the fact we that we desire different depths.
put copies of boost logo in subdirectories
2016-02-07 14:38:06 -08:00

166 lines
8.2 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<section id="safe_numerics.tutorial">
<title>Tutorial and Motivating Examples</title>
<section id="safe_numerics.tutorial.1">
<title>Arithmetic Expressions Can Yield Incorrect Results.</title>
<para>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.</para>
<para>This program demonstrates this problem. The solution is to replace
instances of <code>char</code> type with <code>safe&lt;char&gt;</code>
type.</para>
<programlisting><xi:include href="../../examples/example1.cpp"
parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>
<para>Note that I've used <code>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>int</code> types albeit with different values.</para>
</section>
<section id="safe_numerics.tutorial.2">
<title>Arithmetic Operations can Overflow Silently</title>
<para>A variation of the above is when a value is incremented/decremented
beyond it's domain. This is a common problem with for loops.</para>
<programlisting><xi:include href="../../examples/example2.cpp"
parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>
<para>When variables of unsigned integer type are decremented below zero,
they "roll over" to the highest possible unsigned version of that integer
type. This is a common problem which is generally never detected.</para>
</section>
<section id="safe_numerics.tutorial.4">
<title>Implicit Conversions Change Data Values</title>
<para>A simple assignment or arithmetic expression will convert all the
terms to the same type. Sometimes this can silently change values. For
example, when a signed data variable contains a negative type, assigning
to a unsigned type will be permitted by any C/C++ compiler but will be
treated as large unsigned value. Most modern compilers will emit a compile
time warning when this conversion is performed. The user may then decide
to change some data types or apply a <code>static_cast</code>. This is
less than satisfactory for two reasons:</para>
<para><itemizedlist>
<listitem>
<para>It may be unwieldy to change all the types to signed or
unsigned.</para>
</listitem>
<listitem>
<para>We may believe that our signed type will never contain a
negative value. <code>static_cast</code> changes the data type - not
the data value. If we ignore the any compiler warnings or use a
<code>static_cast</code> to suppress them, we'll fail to detect a
program error when it is committed. This is aways a risk with
casts.</para>
</listitem>
</itemizedlist></para>
<para>This solution is simple, Just replace instances of the <code>int
</code>with <code>safe&lt;int&gt;</code>.<programlisting><xi:include
href="../../examples/example4.cpp" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting></para>
</section>
<section id="safe_numerics.tutorial.10">
<title>Mixing Data Types Can Create Subtle Errors</title>
<para>C++ contains signed and unsigned integer types. In spite of their
names, they function differently which often produces surprising results
for some operands. Program errors from this behavior can be exceedingly
difficult to find. This has lead to recommendations of various ad hoc
"rules" to avoid these problems. It's not always easy to apply these
"rules" to existing code without creating even more bugs. Here is a
typical example of this problem:</para>
<para><programlisting><xi:include href="../../examples/example10.cpp"
parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>Here
is the output of the above program:<screen>example 10: mixing types produces surprising results
Not using safe numerics
10000
4294957296
Using safe numerics
10000
detected error:converted negative value to unsigned
</screen>This solution is simple, Just replace instances of the
<code>int</code>with <code>safe&lt;int&gt;</code>.</para>
</section>
<section id="safe_numerics.tutorial.5">
<title>Array Index Value Can Exceed Array Limits</title>
<para>Using an intrinsic C++ array, it's very easy to exceed array limits.
This can fail to be detected when it occurs and create bugs which are hard
to find. There are several ways to address this, but one of the simplest
would be to use safe_unsigned_range;</para>
<para><programlisting><xi:include href="../../examples/example5.cpp"
parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>Collections
like standard arrays, vectors do array index checking in some function
calls and not in others so this may not be the best example. However it
does illustrate the usage of <code>safe_range&lt;T&gt;</code> for
assigning legal range to variables. This will guarantee that under no
circumstances will the variable contain a value outside of the specified
range.</para>
</section>
<section id="safe_numerics.tutorial.6">
<title>Checking of Input Values Can Be Easily Overlooked</title>
<para>It's way too easy to overlook the checking of parameters received
from outside the current program.<programlisting><xi:include
href="../../examples/example6.cpp" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>Without
safe integer, one will have to insert new code every time an integer
variable is retrieved. This is a tedious and error prone procedure. Here
we have used program input. But in fact this problem can occur with any
externally produced input.</para>
</section>
<section id="safe_numerics.tutorial.7">
<title>Programming by Contract is Too Slow</title>
<para>Programming by Contract is a highly regarded technique. There has
been much written about it has been proposed as an addition to the C++
language <citation>Garcia</citation><citation>Crowl &amp;
Ottosen</citation>. It (mostly) depends upon runtime checking of parameter
and object values upon entry to and exit from every function. This can
slow the program down considerably which in turn undermines the main
motivation for using C++ in the first place! One popular scheme for
addressing this issue is to enable parameter checking only during
debugging and testing which defeats the guarantee of correctness which we
are seeking here! Programming by Contract will never be accepted by
programmers as long as it is associated with significant additional
runtime cost.</para>
<para>The Safe Numerics Library has facilities which, in many cases, can
check guarantee parameter requirements with little or no runtime overhead.
Consider the following example:</para>
<para><programlisting><xi:include href="../../examples/example7.cpp"
parse="text" xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting></para>
<para>In the example above the function convert incurs significant runtime
cost every time the function is called. By using "safe" types, this cost
is moved to moment when the parameters are constructed. Depending on how
the program is constructed, this may totally eliminate extraneous
computations for parameter requirement type checking. In this scenario,
there is no reason to suppress the checking for release mode and our
program can be guaranteed to be always arithmetically correct.</para>
</section>
</section>