253 lines
13 KiB
HTML
253 lines
13 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
|
|
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>Boost.MultiIndex Documentation - Tutorial -Debugging support</title>
|
|
<link rel="stylesheet" href="../style.css" type="text/css">
|
|
<link rel="start" href="../index.html">
|
|
<link rel="prev" href="creation.html">
|
|
<link rel="up" href="index.html">
|
|
<link rel="next" href="techniques.html">
|
|
</head>
|
|
|
|
<body>
|
|
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
|
|
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Debugging support</h1>
|
|
|
|
<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
|
|
Container creation
|
|
</a></div>
|
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
|
Boost.MultiIndex tutorial
|
|
</a></div>
|
|
<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
|
|
Techniques
|
|
</a></div><br clear="all" style="clear: all;">
|
|
|
|
<hr>
|
|
|
|
<h2>Contents</h2>
|
|
|
|
<ul>
|
|
<li><a href="#debugging_support">Debugging support</a></li>
|
|
<li><a href="#safe_mode">Safe mode</a>
|
|
<ul>
|
|
<li><a href="#serialization_and_safe_mode">Serialization and safe mode</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#invariant_check">Invariant-checking mode</a></li>
|
|
</ul>
|
|
|
|
<h2><a name="debugging_support">Debugging support</a></h2>
|
|
|
|
<p>
|
|
The concept of <i>Design by Contract</i>, originally developed as part
|
|
of Bertrand Meyer's <a href="http://www.eiffel.com">Eiffel</a> language,
|
|
revolves around the formulation of a <i>contract</i> between the user
|
|
of a library and the implementor, by which the first is required to
|
|
respect some <i>preconditions</i> on the values passed when invoking
|
|
methods of the library, and the implementor guarantees in return
|
|
that certain constraints on the results are met (<i>postconditions</i>),
|
|
as well as the honoring of specified internal consistency rules, called
|
|
<i>invariants</i>. Eiffel natively supports the three parts of the
|
|
contract just described by means of constructs <code>require</code>,
|
|
<code>ensure</code> and <code>invariant</code>, respectively.
|
|
</p>
|
|
|
|
<p>
|
|
C++ does not enjoy direct support for Design by Contract techniques: these
|
|
are customarily implemented as assertion code, often turned off in
|
|
release mode for performance reasons. Following this approach,
|
|
Boost.MultiIndex provides two distinct debugging modes:
|
|
<ul>
|
|
<li><i>Safe mode</i> checks preconditions on the invocations to the
|
|
facilities of the library,</li>
|
|
<li><i>invariant-checking mode</i> performs post-execution checks aimed
|
|
at ensuring that the internal consistency of the library is preserved.</li>
|
|
</ul>
|
|
These two modes are independent of each other and can be set on or off
|
|
individually. It is important to note that errors detected by safe mode are
|
|
due in principle to faulty code in the user's program, while
|
|
invariant-checking mode detects potential <i>internal</i> bugs in the
|
|
implementation of Boost.MultiIndex.
|
|
</p>
|
|
|
|
<h2><a name="safe_mode">Safe mode</a></h2>
|
|
|
|
<p>
|
|
The idea of adding precondition checking facilities to STL as a debugging aid
|
|
was first introduced by Cay S. Horstmann in his
|
|
<a href="http://www.horstmann.com/safestl.html">Safe STL</a> library and later
|
|
adopted by <a href="http://www.stlport.com/doc/debug_mode.html">STLport Debug
|
|
Mode</a>. Similarly, Boost.MultiIndex features the so-called <i>safe mode</i>
|
|
in which all sorts of preconditions are checked when dealing with iterators
|
|
and functions of the library.
|
|
</p>
|
|
|
|
<p>
|
|
Boost.MultiIndex safe mode is set by globally defining the macro
|
|
<code>BOOST_MULTI_INDEX_ENABLE_SAFE_MODE</code>. Error conditions
|
|
are checked via the macro <code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, which
|
|
by default resolves to a call to <a href="../../../../libs/assert">
|
|
<code>BOOST_ASSERT</code></a>.
|
|
</p>
|
|
|
|
<p>
|
|
If the user decides to define her own version of
|
|
<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, it has to take the form
|
|
</p>
|
|
|
|
<blockquote><pre>
|
|
<span class=identifier>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</span><span class=special>(</span><span class=identifier>expr</span><span class=special>,</span><span class=identifier>error_code</span><span class=special>)</span>
|
|
</pre></blockquote>
|
|
|
|
<p>
|
|
where <code>expr</code> is the condition checked and <code>error_code</code>
|
|
is one value of the <code>safe_mode::error_code</code> enumeration:
|
|
</p>
|
|
|
|
<blockquote><pre>
|
|
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
|
|
|
|
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
|
|
|
|
<span class=keyword>namespace</span> <span class=identifier>safe_mode</span><span class=special>{</span>
|
|
|
|
<span class=keyword>enum</span> <span class=identifier>error_code</span>
|
|
<span class=special>{</span>
|
|
<span class=identifier>invalid_iterator</span><span class=special>,</span> <span class=comment>// vg. default cted or pointing to erased element</span>
|
|
<span class=identifier>not_dereferenceable_iterator</span><span class=special>,</span> <span class=comment>// iterator is not dereferenceable</span>
|
|
<span class=identifier>not_incrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to end of sequence</span>
|
|
<span class=identifier>not_decrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to beginning of sequence</span>
|
|
<span class=identifier>not_owner</span><span class=special>,</span> <span class=comment>// iterator does not belong to the container</span>
|
|
<span class=identifier>not_same_owner</span><span class=special>,</span> <span class=comment>// iterators belong to different containers</span>
|
|
<span class=identifier>invalid_range</span><span class=special>,</span> <span class=comment>// last not reachable from first</span>
|
|
<span class=identifier>inside_range</span><span class=special>,</span> <span class=comment>// iterator lies within a range (and it mustn't)</span>
|
|
<span class=identifier>out_of_bounds</span><span class=special>,</span> <span class=comment>// move attempted beyond container limits</span>
|
|
<span class=identifier>same_container</span> <span class=comment>// containers ought to be different</span>
|
|
<span class=special>};</span>
|
|
|
|
<span class=special>}</span> <span class=comment>// namespace multi_index::safe_mode</span>
|
|
|
|
<span class=special>}</span> <span class=comment>// namespace multi_index</span>
|
|
|
|
<span class=special>}</span> <span class=comment>// namespace boost</span>
|
|
</pre></blockquote>
|
|
|
|
<p>
|
|
For instance, the following replacement of
|
|
<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code> throws an exception instead of
|
|
asserting:
|
|
</p>
|
|
|
|
<blockquote><pre>
|
|
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>/</span><span class=identifier>safe_mode_errors</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
|
|
|
<span class=keyword>struct</span> <span class=identifier>safe_mode_exception</span>
|
|
<span class=special>{</span>
|
|
<span class=identifier>safe_mode_exception</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>safe_mode</span><span class=special>::</span><span class=identifier>error_code</span> <span class=identifier>error_code</span><span class=special>):</span>
|
|
<span class=identifier>error_code</span><span class=special>(</span><span class=identifier>error_code</span><span class=special>)</span>
|
|
<span class=special>{}</span>
|
|
|
|
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>safe_mode</span><span class=special>::</span><span class=identifier>error_code</span> <span class=identifier>error_code</span><span class=special>;</span>
|
|
<span class=special>};</span>
|
|
|
|
<span class=preprocessor>#define</span> <span class=identifier>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</span><span class=special>(</span><span class=identifier>expr</span><span class=special>,</span><span class=identifier>error_code</span><span class=special>)</span> <span class=special>\</span>
|
|
<span class=keyword>if</span><span class=special>(!(</span><span class=identifier>expr</span><span class=special>)){</span><span class=keyword>throw</span> <span class=identifier>safe_mode_exception</span><span class=special>(</span><span class=identifier>error_code</span><span class=special>);}</span>
|
|
|
|
<span class=comment>// This has to go before the inclusion of any header from Boost.MultiIndex,
|
|
// except possibly safe_error_codes.hpp.</span>
|
|
</pre></blockquote>
|
|
|
|
<p>
|
|
Other possibilites, like outputting to a log or firing some kind of alert, are
|
|
also implementable.
|
|
</p>
|
|
|
|
<p>
|
|
<b>Warning:</b> Safe mode adds a very important overhead to the program
|
|
both in terms of space and time used, so in general it should not be set for
|
|
<code>NDEBUG</code> builds. Also, this mode is intended solely as a debugging aid,
|
|
and programs must not rely on it as part of their normal execution flow: in
|
|
particular, no guarantee is made that all possible precondition errors are diagnosed,
|
|
or that the checks remain stable across different versions of the library.
|
|
</p>
|
|
|
|
<h3><a name="serialization_and_safe_mode">Serialization and safe mode</a></h3>
|
|
|
|
<p>
|
|
Iterators restored from an archive are not subject to safe mode checks. This is
|
|
so because it is not possible to automatically know the associated
|
|
<code>multi_index_container</code> of an iterator from the serialization
|
|
information alone. However, if desired, a restored iterator can be converted to a
|
|
checked value by using the following workaround:
|
|
</p>
|
|
|
|
<blockquote><pre>
|
|
<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
|
|
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special><</span><span class=number>1</span><span class=special>>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>;</span>
|
|
|
|
<span class=comment>// restore es and it from an archive ar</span>
|
|
<span class=identifier>ar</span><span class=special>>></span><span class=identifier>es</span><span class=special>;</span>
|
|
<span class=identifier>ar</span><span class=special>>></span><span class=identifier>it</span><span class=special>;</span> <span class=comment>// it won't benefit from safe mode checks
|
|
|
|
// Turn it into a checked value by providing Boost.MultiIndex
|
|
// with info about the associated container.
|
|
// This statement has virtually zero cost if safe mode is turned off.</span>
|
|
<span class=identifier>it</span><span class=special>=</span><span class=identifier>es</span><span class=special>.</span><span class=identifier>project</span><span class=special><</span><span class=number>1</span><span class=special>>(</span><span class=identifier>it</span><span class=special>);</span>
|
|
</pre></blockquote>
|
|
|
|
<h2><a name="invariant_check">Invariant-checking mode</a></h2>
|
|
|
|
<p>
|
|
The so called <i>invariant-checking mode</i> of Boost.MultiIndex can be
|
|
set by globally defining the macro
|
|
<code>BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING</code>.
|
|
When this mode is in effect, all public functions of Boost.MultiIndex
|
|
will perform post-execution tests aimed at ensuring that the basic
|
|
internal invariants of the data structures managed are preserved.
|
|
</p>
|
|
|
|
<p>
|
|
If an invariant test fails, Boost.MultiIndex will indicate the failure
|
|
by means of the unary macro <code>BOOST_MULTI_INDEX_INVARIANT_ASSERT</code>.
|
|
Unless the user provides a definition for this macro, it defaults to
|
|
<a href="../../../../libs/assert">
|
|
<code>BOOST_ASSERT</code></a>. Any assertion of this kind should
|
|
be regarded in principle as a bug in the library. Please report such
|
|
problems, along with as much contextual information as possible, to the
|
|
maintainer of the library.
|
|
</p>
|
|
|
|
<p>
|
|
It is recommended that users of Boost.MultiIndex always set the
|
|
invariant-checking mode in debug builds.
|
|
</p>
|
|
|
|
<hr>
|
|
|
|
<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
|
|
Container creation
|
|
</a></div>
|
|
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
|
|
Boost.MultiIndex tutorial
|
|
</a></div>
|
|
<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
|
|
Techniques
|
|
</a></div><br clear="all" style="clear: all;">
|
|
|
|
<br>
|
|
|
|
<p>Revised July 07th 2017</p>
|
|
|
|
<p>© Copyright 2003-2017 Joaquín M López Muñoz.
|
|
Distributed under the Boost Software
|
|
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
|
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
|
http://www.boost.org/LICENSE_1_0.txt</a>)
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|