blob: 3853e84a94d77791d99696ebc4a4f85d1c8dbfcd [file] [log] [blame]
Brian Silverman3cbbaca2018-08-04 23:38:07 -07001<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
2
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Boost.MultiIndex Documentation - Tutorial -Debugging support</title>
7<link rel="stylesheet" href="../style.css" type="text/css">
8<link rel="start" href="../index.html">
9<link rel="prev" href="creation.html">
10<link rel="up" href="index.html">
11<link rel="next" href="techniques.html">
12</head>
13
14<body>
15<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
16"middle" width="277" height="86">Boost.MultiIndex Tutorial: Debugging support</h1>
17
18<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
19Container creation
20</a></div>
21<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
22Boost.MultiIndex tutorial
23</a></div>
24<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
25Techniques
26</a></div><br clear="all" style="clear: all;">
27
28<hr>
29
30<h2>Contents</h2>
31
32<ul>
33 <li><a href="#debugging_support">Debugging support</a></li>
34 <li><a href="#safe_mode">Safe mode</a>
35 <ul>
36 <li><a href="#serialization_and_safe_mode">Serialization and safe mode</a></li>
37 </ul>
38 </li>
39 <li><a href="#invariant_check">Invariant-checking mode</a></li>
40</ul>
41
42<h2><a name="debugging_support">Debugging support</a></h2>
43
44<p>
45The concept of <i>Design by Contract</i>, originally developed as part
46of Bertrand Meyer's <a href="http://www.eiffel.com">Eiffel</a> language,
47revolves around the formulation of a <i>contract</i> between the user
48of a library and the implementor, by which the first is required to
49respect some <i>preconditions</i> on the values passed when invoking
50methods of the library, and the implementor guarantees in return
51that certain constraints on the results are met (<i>postconditions</i>),
52as well as the honoring of specified internal consistency rules, called
53<i>invariants</i>. Eiffel natively supports the three parts of the
54contract just described by means of constructs <code>require</code>,
55<code>ensure</code> and <code>invariant</code>, respectively.
56</p>
57
58<p>
59C++ does not enjoy direct support for Design by Contract techniques: these
60are customarily implemented as assertion code, often turned off in
61release mode for performance reasons. Following this approach,
62Boost.MultiIndex provides two distinct debugging modes:
63<ul>
64 <li><i>Safe mode</i> checks preconditions on the invocations to the
65 facilities of the library,</li>
66 <li><i>invariant-checking mode</i> performs post-execution checks aimed
67 at ensuring that the internal consistency of the library is preserved.</li>
68</ul>
69These two modes are independent of each other and can be set on or off
70individually. It is important to note that errors detected by safe mode are
71due in principle to faulty code in the user's program, while
72invariant-checking mode detects potential <i>internal</i> bugs in the
73implementation of Boost.MultiIndex.
74</p>
75
76<h2><a name="safe_mode">Safe mode</a></h2>
77
78<p>
79The idea of adding precondition checking facilities to STL as a debugging aid
80was first introduced by Cay S. Horstmann in his
81<a href="http://www.horstmann.com/safestl.html">Safe STL</a> library and later
82adopted by <a href="http://www.stlport.com/doc/debug_mode.html">STLport Debug
83Mode</a>. Similarly, Boost.MultiIndex features the so-called <i>safe mode</i>
84in which all sorts of preconditions are checked when dealing with iterators
85and functions of the library.
86</p>
87
88<p>
89Boost.MultiIndex safe mode is set by globally defining the macro
90<code>BOOST_MULTI_INDEX_ENABLE_SAFE_MODE</code>. Error conditions
91are checked via the macro <code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, which
92by default resolves to a call to <a href="../../../../libs/assert">
93<code>BOOST_ASSERT</code></a>.
94</p>
95
96<p>
97If the user decides to define her own version of
98<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, it has to take the form
99</p>
100
101<blockquote><pre>
102<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>
103</pre></blockquote>
104
105<p>
106where <code>expr</code> is the condition checked and <code>error_code</code>
107is one value of the <code>safe_mode::error_code</code> enumeration:
108</p>
109
110<blockquote><pre>
111<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
112
113<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
114
115<span class=keyword>namespace</span> <span class=identifier>safe_mode</span><span class=special>{</span>
116
117<span class=keyword>enum</span> <span class=identifier>error_code</span>
118<span class=special>{</span>
119 <span class=identifier>invalid_iterator</span><span class=special>,</span> <span class=comment>// vg. default cted or pointing to erased element</span>
120 <span class=identifier>not_dereferenceable_iterator</span><span class=special>,</span> <span class=comment>// iterator is not dereferenceable</span>
121 <span class=identifier>not_incrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to end of sequence</span>
122 <span class=identifier>not_decrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to beginning of sequence</span>
123 <span class=identifier>not_owner</span><span class=special>,</span> <span class=comment>// iterator does not belong to the container</span>
124 <span class=identifier>not_same_owner</span><span class=special>,</span> <span class=comment>// iterators belong to different containers</span>
125 <span class=identifier>invalid_range</span><span class=special>,</span> <span class=comment>// last not reachable from first</span>
126 <span class=identifier>inside_range</span><span class=special>,</span> <span class=comment>// iterator lies within a range (and it mustn't)</span>
127 <span class=identifier>out_of_bounds</span><span class=special>,</span> <span class=comment>// move attempted beyond container limits</span>
128 <span class=identifier>same_container</span> <span class=comment>// containers ought to be different</span>
129<span class=special>};</span>
130
131<span class=special>}</span> <span class=comment>// namespace multi_index::safe_mode</span>
132
133<span class=special>}</span> <span class=comment>// namespace multi_index</span>
134
135<span class=special>}</span> <span class=comment>// namespace boost</span>
136</pre></blockquote>
137
138<p>
139For instance, the following replacement of
140<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code> throws an exception instead of
141asserting:
142</p>
143
144<blockquote><pre>
145<span class=preprocessor>#include</span> <span class=special>&lt;</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>&gt;</span>
146
147<span class=keyword>struct</span> <span class=identifier>safe_mode_exception</span>
148<span class=special>{</span>
149 <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>
150 <span class=identifier>error_code</span><span class=special>(</span><span class=identifier>error_code</span><span class=special>)</span>
151 <span class=special>{}</span>
152
153 <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>
154<span class=special>};</span>
155
156<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>
157<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>
158
159<span class=comment>// This has to go before the inclusion of any header from Boost.MultiIndex,
160// except possibly safe_error_codes.hpp.</span>
161</pre></blockquote>
162
163<p>
164Other possibilites, like outputting to a log or firing some kind of alert, are
165also implementable.
166</p>
167
168<p>
169<b>Warning:</b> Safe mode adds a very important overhead to the program
170both in terms of space and time used, so in general it should not be set for
171<code>NDEBUG</code> builds. Also, this mode is intended solely as a debugging aid,
172and programs must not rely on it as part of their normal execution flow: in
173particular, no guarantee is made that all possible precondition errors are diagnosed,
174or that the checks remain stable across different versions of the library.
175</p>
176
177<h3><a name="serialization_and_safe_mode">Serialization and safe mode</a></h3>
178
179<p>
180Iterators restored from an archive are not subject to safe mode checks. This is
181so because it is not possible to automatically know the associated
182<code>multi_index_container</code> of an iterator from the serialization
183information alone. However, if desired, a restored iterator can be converted to a
184checked value by using the following workaround:
185</p>
186
187<blockquote><pre>
188<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
189<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>;</span>
190
191<span class=comment>// restore es and it from an archive ar</span>
192<span class=identifier>ar</span><span class=special>&gt;&gt;</span><span class=identifier>es</span><span class=special>;</span>
193<span class=identifier>ar</span><span class=special>&gt;&gt;</span><span class=identifier>it</span><span class=special>;</span> <span class=comment>// it won't benefit from safe mode checks
194
195// Turn it into a checked value by providing Boost.MultiIndex
196// with info about the associated container.
197// This statement has virtually zero cost if safe mode is turned off.</span>
198<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>&lt;</span><span class=number>1</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
199</pre></blockquote>
200
201<h2><a name="invariant_check">Invariant-checking mode</a></h2>
202
203<p>
204The so called <i>invariant-checking mode</i> of Boost.MultiIndex can be
205set by globally defining the macro
206<code>BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING</code>.
207When this mode is in effect, all public functions of Boost.MultiIndex
208will perform post-execution tests aimed at ensuring that the basic
209internal invariants of the data structures managed are preserved.
210</p>
211
212<p>
213If an invariant test fails, Boost.MultiIndex will indicate the failure
214by means of the unary macro <code>BOOST_MULTI_INDEX_INVARIANT_ASSERT</code>.
215Unless the user provides a definition for this macro, it defaults to
216<a href="../../../../libs/assert">
217<code>BOOST_ASSERT</code></a>. Any assertion of this kind should
218be regarded in principle as a bug in the library. Please report such
219problems, along with as much contextual information as possible, to the
220maintainer of the library.
221</p>
222
223<p>
224It is recommended that users of Boost.MultiIndex always set the
225invariant-checking mode in debug builds.
226</p>
227
228<hr>
229
230<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
231Container creation
232</a></div>
233<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
234Boost.MultiIndex tutorial
235</a></div>
236<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
237Techniques
238</a></div><br clear="all" style="clear: all;">
239
240<br>
241
242<p>Revised July 07th 2017</p>
243
244<p>&copy; Copyright 2003-2017 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
245Distributed under the Boost Software
246License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
247LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
248http://www.boost.org/LICENSE_1_0.txt</a>)
249</p>
250
251</body>
252</html>