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
166 lines
8.2 KiB
XML
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<char></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<int></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<int></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<T></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 &
|
|
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>
|