Brian Silverman | 3cbbaca | 2018-08-04 23:38:07 -0700 | [diff] [blame^] | 1 | <!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> |
| 19 | Container creation |
| 20 | </a></div> |
| 21 | <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br> |
| 22 | Boost.MultiIndex tutorial |
| 23 | </a></div> |
| 24 | <div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br> |
| 25 | Techniques |
| 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> |
| 45 | The concept of <i>Design by Contract</i>, originally developed as part |
| 46 | of Bertrand Meyer's <a href="http://www.eiffel.com">Eiffel</a> language, |
| 47 | revolves around the formulation of a <i>contract</i> between the user |
| 48 | of a library and the implementor, by which the first is required to |
| 49 | respect some <i>preconditions</i> on the values passed when invoking |
| 50 | methods of the library, and the implementor guarantees in return |
| 51 | that certain constraints on the results are met (<i>postconditions</i>), |
| 52 | as well as the honoring of specified internal consistency rules, called |
| 53 | <i>invariants</i>. Eiffel natively supports the three parts of the |
| 54 | contract just described by means of constructs <code>require</code>, |
| 55 | <code>ensure</code> and <code>invariant</code>, respectively. |
| 56 | </p> |
| 57 | |
| 58 | <p> |
| 59 | C++ does not enjoy direct support for Design by Contract techniques: these |
| 60 | are customarily implemented as assertion code, often turned off in |
| 61 | release mode for performance reasons. Following this approach, |
| 62 | Boost.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> |
| 69 | These two modes are independent of each other and can be set on or off |
| 70 | individually. It is important to note that errors detected by safe mode are |
| 71 | due in principle to faulty code in the user's program, while |
| 72 | invariant-checking mode detects potential <i>internal</i> bugs in the |
| 73 | implementation of Boost.MultiIndex. |
| 74 | </p> |
| 75 | |
| 76 | <h2><a name="safe_mode">Safe mode</a></h2> |
| 77 | |
| 78 | <p> |
| 79 | The idea of adding precondition checking facilities to STL as a debugging aid |
| 80 | was first introduced by Cay S. Horstmann in his |
| 81 | <a href="http://www.horstmann.com/safestl.html">Safe STL</a> library and later |
| 82 | adopted by <a href="http://www.stlport.com/doc/debug_mode.html">STLport Debug |
| 83 | Mode</a>. Similarly, Boost.MultiIndex features the so-called <i>safe mode</i> |
| 84 | in which all sorts of preconditions are checked when dealing with iterators |
| 85 | and functions of the library. |
| 86 | </p> |
| 87 | |
| 88 | <p> |
| 89 | Boost.MultiIndex safe mode is set by globally defining the macro |
| 90 | <code>BOOST_MULTI_INDEX_ENABLE_SAFE_MODE</code>. Error conditions |
| 91 | are checked via the macro <code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, which |
| 92 | by default resolves to a call to <a href="../../../../libs/assert"> |
| 93 | <code>BOOST_ASSERT</code></a>. |
| 94 | </p> |
| 95 | |
| 96 | <p> |
| 97 | If 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> |
| 106 | where <code>expr</code> is the condition checked and <code>error_code</code> |
| 107 | is 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> |
| 139 | For instance, the following replacement of |
| 140 | <code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code> throws an exception instead of |
| 141 | asserting: |
| 142 | </p> |
| 143 | |
| 144 | <blockquote><pre> |
| 145 | <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> |
| 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> |
| 164 | Other possibilites, like outputting to a log or firing some kind of alert, are |
| 165 | also implementable. |
| 166 | </p> |
| 167 | |
| 168 | <p> |
| 169 | <b>Warning:</b> Safe mode adds a very important overhead to the program |
| 170 | both 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, |
| 172 | and programs must not rely on it as part of their normal execution flow: in |
| 173 | particular, no guarantee is made that all possible precondition errors are diagnosed, |
| 174 | or 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> |
| 180 | Iterators restored from an archive are not subject to safe mode checks. This is |
| 181 | so because it is not possible to automatically know the associated |
| 182 | <code>multi_index_container</code> of an iterator from the serialization |
| 183 | information alone. However, if desired, a restored iterator can be converted to a |
| 184 | checked 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><</span><span class=number>1</span><span class=special>>::</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>>></span><span class=identifier>es</span><span class=special>;</span> |
| 193 | <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 |
| 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><</span><span class=number>1</span><span class=special>>(</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> |
| 204 | The so called <i>invariant-checking mode</i> of Boost.MultiIndex can be |
| 205 | set by globally defining the macro |
| 206 | <code>BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING</code>. |
| 207 | When this mode is in effect, all public functions of Boost.MultiIndex |
| 208 | will perform post-execution tests aimed at ensuring that the basic |
| 209 | internal invariants of the data structures managed are preserved. |
| 210 | </p> |
| 211 | |
| 212 | <p> |
| 213 | If an invariant test fails, Boost.MultiIndex will indicate the failure |
| 214 | by means of the unary macro <code>BOOST_MULTI_INDEX_INVARIANT_ASSERT</code>. |
| 215 | Unless 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 |
| 218 | be regarded in principle as a bug in the library. Please report such |
| 219 | problems, along with as much contextual information as possible, to the |
| 220 | maintainer of the library. |
| 221 | </p> |
| 222 | |
| 223 | <p> |
| 224 | It is recommended that users of Boost.MultiIndex always set the |
| 225 | invariant-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> |
| 231 | Container creation |
| 232 | </a></div> |
| 233 | <div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br> |
| 234 | Boost.MultiIndex tutorial |
| 235 | </a></div> |
| 236 | <div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br> |
| 237 | Techniques |
| 238 | </a></div><br clear="all" style="clear: all;"> |
| 239 | |
| 240 | <br> |
| 241 | |
| 242 | <p>Revised July 07th 2017</p> |
| 243 | |
| 244 | <p>© Copyright 2003-2017 Joaquín M López Muñoz. |
| 245 | Distributed under the Boost Software |
| 246 | License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt"> |
| 247 | LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> |
| 248 | http://www.boost.org/LICENSE_1_0.txt</a>) |
| 249 | </p> |
| 250 | |
| 251 | </body> |
| 252 | </html> |