| OLD | NEW |
| (Empty) |
| 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
| 2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or
g/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
| 3 <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" /><title>Design</title><meta name="generator
" content="DocBook XSL Stylesheets V1.74.0" /><meta name="keywords" content="
0; C++ , library , debug " />
<meta name="keywords" content=" ISO C++ , library&#
10; " /><link rel="home" href="../spine.html" title="The GNU C++ Library Docu
mentation" /><link rel="up" href="debug_mode.html" title="Chapter 30. Debug Mode
" /><link rel="prev" href="bk01pt12ch30s03.html" title="Using" /><link rel="next
" href="parallel_mode.html" title="Chapter 31. Parallel Mode" /></head><body><di
v class="navheader"><table width="100%" summary="Navigation header"><tr><th cols
pan="3" align="center">Design</th></tr><tr><td width="20%" align="left"><a acces
skey="p" href="bk01pt12ch30s03.html">Prev</a> </td><th width="60%" align="center
">Chapter 30. Debug Mode</th><td width="20%" align="right"> <a accesskey="n" hre
f="parallel_mode.html">Next</a></td></tr></table><hr /></div><div class="sect1"
lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style
="clear: both"><a id="manual.ext.debug_mode.design"></a>Design</h2></div></div><
/div><p> | |
| 4 </p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><di
v><h3 class="title"><a id="manual.ext.debug_mode.design.goals"></a>Goals</h3></d
iv></div></div><p> | |
| 5 </p><p> The libstdc++ debug mode replaces unsafe (but efficient) standard | |
| 6 containers and iterators with semantically equivalent safe standard | |
| 7 containers and iterators to aid in debugging user programs. The | |
| 8 following goals directed the design of the libstdc++ debug mode:</p><div class
="itemizedlist"><ul type="disc"><li><p><span class="emphasis"><em>Correctness</e
m></span>: the libstdc++ debug mode must not change | |
| 9 the semantics of the standard library for all cases specified in | |
| 10 the ANSI/ISO C++ standard. The essence of this constraint is that | |
| 11 any valid C++ program should behave in the same manner regardless | |
| 12 of whether it is compiled with debug mode or release mode. In | |
| 13 particular, entities that are defined in namespace std in release | |
| 14 mode should remain defined in namespace std in debug mode, so that | |
| 15 legal specializations of namespace std entities will remain | |
| 16 valid. A program that is not valid C++ (e.g., invokes undefined | |
| 17 behavior) is not required to behave similarly, although the debug | |
| 18 mode will abort with a diagnostic when it detects undefined | |
| 19 behavior.</p></li><li><p><span class="emphasis"><em>Performance</em></span>:
the additional of the libstdc++ debug mode | |
| 20 must not affect the performance of the library when it is compiled | |
| 21 in release mode. Performance of the libstdc++ debug mode is | |
| 22 secondary (and, in fact, will be worse than the release | |
| 23 mode).</p></li><li><p><span class="emphasis"><em>Usability</em></span>: the
libstdc++ debug mode should be easy to | |
| 24 use. It should be easily incorporated into the user's development | |
| 25 environment (e.g., by requiring only a single new compiler switch) | |
| 26 and should produce reasonable diagnostics when it detects a | |
| 27 problem with the user program. Usability also involves detection | |
| 28 of errors when using the debug mode incorrectly, e.g., by linking | |
| 29 a release-compiled object against a debug-compiled object if in | |
| 30 fact the resulting program will not run correctly.</p></li><li><p><span clas
s="emphasis"><em>Minimize recompilation</em></span>: While it is expected that | |
| 31 users recompile at least part of their program to use debug | |
| 32 mode, the amount of recompilation affects the | |
| 33 detect-compile-debug turnaround time. This indirectly affects the | |
| 34 usefulness of the debug mode, because debugging some applications | |
| 35 may require rebuilding a large amount of code, which may not be | |
| 36 feasible when the suspect code may be very localized. There are | |
| 37 several levels of conformance to this requirement, each with its | |
| 38 own usability and implementation characteristics. In general, the | |
| 39 higher-numbered conformance levels are more usable (i.e., require | |
| 40 less recompilation) but are more complicated to implement than | |
| 41 the lower-numbered conformance levels. | |
| 42 </p><div class="orderedlist"><ol type="1"><li><p><span class="emphasis"><e
m>Full recompilation</em></span>: The user must recompile his or | |
| 43 her entire application and all C++ libraries it depends on, | |
| 44 including the C++ standard library that ships with the | |
| 45 compiler. This must be done even if only a small part of the | |
| 46 program can use debugging features.</p></li><li><p><span class="emphasis
"><em>Full user recompilation</em></span>: The user must recompile | |
| 47 his or her entire application and all C++ libraries it depends | |
| 48 on, but not the C++ standard library itself. This must be done | |
| 49 even if only a small part of the program can use debugging | |
| 50 features. This can be achieved given a full recompilation | |
| 51 system by compiling two versions of the standard library when | |
| 52 the compiler is installed and linking against the appropriate | |
| 53 one, e.g., a multilibs approach.</p></li><li><p><span class="emphasis"><
em>Partial recompilation</em></span>: The user must recompile the | |
| 54 parts of his or her application and the C++ libraries it | |
| 55 depends on that will use the debugging facilities | |
| 56 directly. This means that any code that uses the debuggable | |
| 57 standard containers would need to be recompiled, but code | |
| 58 that does not use them (but may, for instance, use IOStreams) | |
| 59 would not have to be recompiled.</p></li><li><p><span class="emphasis"><
em>Per-use recompilation</em></span>: The user must recompile the | |
| 60 parts of his or her application and the C++ libraries it | |
| 61 depends on where debugging should occur, and any other code | |
| 62 that interacts with those containers. This means that a set of | |
| 63 translation units that accesses a particular standard | |
| 64 container instance may either be compiled in release mode (no | |
| 65 checking) or debug mode (full checking), but must all be | |
| 66 compiled in the same way; a translation unit that does not see | |
| 67 that standard container instance need not be recompiled. This | |
| 68 also means that a translation unit <span class="emphasis"><em>A</em></sp
an> that contains a | |
| 69 particular instantiation | |
| 70 (say, <code class="code">std::vector<int></code>) compiled in rele
ase | |
| 71 mode can be linked against a translation unit <span class="emphasis"><em
>B</em></span> that | |
| 72 contains the same instantiation compiled in debug mode (a | |
| 73 feature not present with partial recompilation). While this | |
| 74 behavior is technically a violation of the One Definition | |
| 75 Rule, this ability tends to be very important in | |
| 76 practice. The libstdc++ debug mode supports this level of | |
| 77 recompilation. </p></li><li><p><span class="emphasis"><em>Per-unit recom
pilation</em></span>: The user must only | |
| 78 recompile the translation units where checking should occur, | |
| 79 regardless of where debuggable standard containers are | |
| 80 used. This has also been dubbed "<code class="code">-g</code> mode", | |
| 81 because the <code class="code">-g</code> compiler switch works in this w
ay, | |
| 82 emitting debugging information at a per--translation-unit | |
| 83 granularity. We believe that this level of recompilation is in | |
| 84 fact not possible if we intend to supply safe iterators, leave | |
| 85 the program semantics unchanged, and not regress in | |
| 86 performance under release mode because we cannot associate | |
| 87 extra information with an iterator (to form a safe iterator) | |
| 88 without either reserving that space in release mode | |
| 89 (performance regression) or allocating extra memory associated | |
| 90 with each iterator with <code class="code">new</code> (changes the progr
am | |
| 91 semantics).</p></li></ol></div><p> | |
| 92 </p></li></ul></div></div><div class="sect2" lang="en" xml:lang="en"><div cl
ass="titlepage"><div><div><h3 class="title"><a id="manual.ext.debug_mode.design.
methods"></a>Methods</h3></div></div></div><p> | |
| 93 </p><p>This section provides an overall view of the design of the | |
| 94 libstdc++ debug mode and details the relationship between design | |
| 95 decisions and the stated design goals.</p><div class="sect3" lang="en" xml:lan
g="en"><div class="titlepage"><div><div><h4 class="title"><a id="debug_mode.desi
gn.methods.wrappers"></a>The Wrapper Model</h4></div></div></div><p>The libstdc+
+ debug mode uses a wrapper model where the debugging | |
| 96 versions of library components (e.g., iterators and containers) form | |
| 97 a layer on top of the release versions of the library | |
| 98 components. The debugging components first verify that the operation | |
| 99 is correct (aborting with a diagnostic if an error is found) and | |
| 100 will then forward to the underlying release-mode container that will | |
| 101 perform the actual work. This design decision ensures that we cannot | |
| 102 regress release-mode performance (because the release-mode | |
| 103 containers are left untouched) and partially enables <a class="ulink" href="#m
ixing" target="_top">mixing debug and release code</a> at link time, | |
| 104 although that will not be discussed at this time.</p><p>Two types of wrappers
are used in the implementation of the debug | |
| 105 mode: container wrappers and iterator wrappers. The two types of | |
| 106 wrappers interact to maintain relationships between iterators and | |
| 107 their associated containers, which are necessary to detect certain | |
| 108 types of standard library usage errors such as dereferencing | |
| 109 past-the-end iterators or inserting into a container using an | |
| 110 iterator from a different container.</p><div class="sect4" lang="en" xml:lang=
"en"><div class="titlepage"><div><div><h5 class="title"><a id="debug_mode.design
.methods.safe_iter"></a>Safe Iterators</h5></div></div></div><p>Iterator wrapper
s provide a debugging layer over any iterator that | |
| 111 is attached to a particular container, and will manage the | |
| 112 information detailing the iterator's state (singular, | |
| 113 dereferenceable, etc.) and tracking the container to which the | |
| 114 iterator is attached. Because iterators have a well-defined, common | |
| 115 interface the iterator wrapper is implemented with the iterator | |
| 116 adaptor class template <code class="code">__gnu_debug::_Safe_iterator</code>, | |
| 117 which takes two template parameters:</p><div class="itemizedlist"><ul type="di
sc"><li><p><code class="code">Iterator</code>: The underlying iterator type, whi
ch must | |
| 118 be either the <code class="code">iterator</code> or <code class="code">const
_iterator</code> | |
| 119 typedef from the sequence type this iterator can reference.</p></li><li><p><
code class="code">Sequence</code>: The type of sequence that this iterator | |
| 120 references. This sequence must be a safe sequence (discussed below) | |
| 121 whose <code class="code">iterator</code> or <code class="code">const_iterator<
/code> typedef | |
| 122 is the type of the safe iterator.</p></li></ul></div></div><div class="sect4"
lang="en" xml:lang="en"><div class="titlepage"><div><div><h5 class="title"><a id
="debug_mode.design.methods.safe_seq"></a>Safe Sequences (Containers)</h5></div>
</div></div><p>Container wrappers provide a debugging layer over a particular | |
| 123 container type. Because containers vary greatly in the member | |
| 124 functions they support and the semantics of those member functions | |
| 125 (especially in the area of iterator invalidation), container | |
| 126 wrappers are tailored to the container they reference, e.g., the | |
| 127 debugging version of <code class="code">std::list</code> duplicates the entire | |
| 128 interface of <code class="code">std::list</code>, adding additional semantic | |
| 129 checks and then forwarding operations to the | |
| 130 real <code class="code">std::list</code> (a public base class of the debugging | |
| 131 version) as appropriate. However, all safe containers inherit from | |
| 132 the class template <code class="code">__gnu_debug::_Safe_sequence</code>, | |
| 133 instantiated with the type of the safe container itself (an instance | |
| 134 of the curiously recurring template pattern).</p><p>The iterators of a contain
er wrapper will be | |
| 135 <a class="ulink" href="#safe_iterator" target="_top">safe iterators</a> that r
eference sequences | |
| 136 of this type and wrap the iterators provided by the release-mode | |
| 137 base class. The debugging container will use only the safe | |
| 138 iterators within its own interface (therefore requiring the user to | |
| 139 use safe iterators, although this does not change correct user | |
| 140 code) and will communicate with the release-mode base class with | |
| 141 only the underlying, unsafe, release-mode iterators that the base | |
| 142 class exports.</p><p> The debugging version of <code class="code">std::list</c
ode> will have the | |
| 143 following basic structure:</p><pre class="programlisting"> | |
| 144 template<typename _Tp, typename _Allocator = allocator<_Tp> | |
| 145 class debug-list : | |
| 146 public release-list<_Tp, _Allocator>, | |
| 147 public __gnu_debug::_Safe_sequence<debug-list<_Tp, _Allocator> > | |
| 148 { | |
| 149 typedef release-list<_Tp, _Allocator> _Base; | |
| 150 typedef debug-list<_Tp, _Allocator> _Self; | |
| 151 | |
| 152 public: | |
| 153 typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, _Self>
iterator; | |
| 154 typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, _Self
> const_iterator; | |
| 155 | |
| 156 // duplicate std::list interface with debugging semantics | |
| 157 }; | |
| 158 </pre></div></div><div class="sect3" lang="en" xml:lang="en"><div class="titlepa
ge"><div><div><h4 class="title"><a id="debug_mode.design.methods.precond"></a>Pr
econdition Checking</h4></div></div></div><p>The debug mode operates primarily b
y checking the preconditions of | |
| 159 all standard library operations that it supports. Preconditions that | |
| 160 are always checked (regardless of whether or not we are in debug | |
| 161 mode) are checked via the <code class="code">__check_xxx</code> macros defined | |
| 162 and documented in the source | |
| 163 file <code class="code">include/debug/debug.h</code>. Preconditions that may o
r | |
| 164 may not be checked, depending on the debug-mode | |
| 165 macro <code class="code">_GLIBCXX_DEBUG</code>, are checked via | |
| 166 the <code class="code">__requires_xxx</code> macros defined and documented in
the | |
| 167 same source file. Preconditions are validated using any additional | |
| 168 information available at run-time, e.g., the containers that are | |
| 169 associated with a particular iterator, the position of the iterator | |
| 170 within those containers, the distance between two iterators that may | |
| 171 form a valid range, etc. In the absence of suitable information, | |
| 172 e.g., an input iterator that is not a safe iterator, these | |
| 173 precondition checks will silently succeed.</p><p>The majority of precondition
checks use the aforementioned macros, | |
| 174 which have the secondary benefit of having prewritten debug | |
| 175 messages that use information about the current status of the | |
| 176 objects involved (e.g., whether an iterator is singular or what | |
| 177 sequence it is attached to) along with some static information | |
| 178 (e.g., the names of the function parameters corresponding to the | |
| 179 objects involved). When not using these macros, the debug mode uses | |
| 180 either the debug-mode assertion | |
| 181 macro <code class="code">_GLIBCXX_DEBUG_ASSERT</code> , its pedantic | |
| 182 cousin <code class="code">_GLIBCXX_DEBUG_PEDASSERT</code>, or the assertion | |
| 183 check macro that supports more advance formulation of error | |
| 184 messages, <code class="code">_GLIBCXX_DEBUG_VERIFY</code>. These macros are | |
| 185 documented more thoroughly in the debug mode source code.</p></div><div class=
"sect3" lang="en" xml:lang="en"><div class="titlepage"><div><div><h4 class="titl
e"><a id="debug_mode.design.methods.coexistence"></a>Release- and debug-mode coe
xistence</h4></div></div></div><p>The libstdc++ debug mode is the first debug mo
de we know of that | |
| 186 is able to provide the "Per-use recompilation" (4) guarantee, that | |
| 187 allows release-compiled and debug-compiled code to be linked and | |
| 188 executed together without causing unpredictable behavior. This | |
| 189 guarantee minimizes the recompilation that users are required to | |
| 190 perform, shortening the detect-compile-debug bug hunting cycle | |
| 191 and making the debug mode easier to incorporate into development | |
| 192 environments by minimizing dependencies.</p><p>Achieving link- and run-time co
existence is not a trivial | |
| 193 implementation task. To achieve this goal we required a small | |
| 194 extension to the GNU C++ compiler (described in the GCC Manual for | |
| 195 C++ Extensions, see <a class="ulink" href="http://gcc.gnu.org/onlinedocs/gcc/S
trong-Using.html" target="_top">strong | |
| 196 using</a>), and a complex organization of debug- and | |
| 197 release-modes. The end result is that we have achieved per-use | |
| 198 recompilation but have had to give up some checking of the | |
| 199 <code class="code">std::basic_string</code> class template (namely, safe | |
| 200 iterators). | |
| 201 </p><div class="sect4" lang="en" xml:lang="en"><div class="titlepage"><div><div>
<h5 class="title"><a id="methods.coexistence.compile"></a>Compile-time coexisten
ce of release- and debug-mode components</h5></div></div></div><p>Both the relea
se-mode components and the debug-mode | |
| 202 components need to exist within a single translation unit so that | |
| 203 the debug versions can wrap the release versions. However, only one | |
| 204 of these components should be user-visible at any particular | |
| 205 time with the standard name, e.g., <code class="code">std::list</code>. </p><p
>In release mode, we define only the release-mode version of the | |
| 206 component with its standard name and do not include the debugging | |
| 207 component at all. The release mode version is defined within the | |
| 208 namespace <code class="code">std</code>. Minus the namespace associations, thi
s | |
| 209 method leaves the behavior of release mode completely unchanged from | |
| 210 its behavior prior to the introduction of the libstdc++ debug | |
| 211 mode. Here's an example of what this ends up looking like, in | |
| 212 C++.</p><pre class="programlisting"> | |
| 213 namespace std | |
| 214 { | |
| 215 template<typename _Tp, typename _Alloc = allocator<_Tp> > | |
| 216 class list | |
| 217 { | |
| 218 // ... | |
| 219 }; | |
| 220 } // namespace std | |
| 221 </pre><p>In debug mode we include the release-mode container (which is now | |
| 222 defined in in the namespace <code class="code">__norm</code>) and also the | |
| 223 debug-mode container. The debug-mode container is defined within the | |
| 224 namespace <code class="code">__debug</code>, which is associated with namespace | |
| 225 <code class="code">std</code> via the GNU namespace association extension. This | |
| 226 method allows the debug and release versions of the same component to | |
| 227 coexist at compile-time and link-time without causing an unreasonable | |
| 228 maintenance burden, while minimizing confusion. Again, this boils down | |
| 229 to C++ code as follows:</p><pre class="programlisting"> | |
| 230 namespace std | |
| 231 { | |
| 232 namespace __norm | |
| 233 { | |
| 234 template<typename _Tp, typename _Alloc = allocator<_Tp> > | |
| 235 class list | |
| 236 { | |
| 237 // ... | |
| 238 }; | |
| 239 } // namespace __gnu_norm | |
| 240 | |
| 241 namespace __debug | |
| 242 { | |
| 243 template<typename _Tp, typename _Alloc = allocator<_Tp> > | |
| 244 class list | |
| 245 : public __norm::list<_Tp, _Alloc>, | |
| 246 public __gnu_debug::_Safe_sequence<list<_Tp, _Alloc> > | |
| 247 { | |
| 248 // ... | |
| 249 }; | |
| 250 } // namespace __norm | |
| 251 | |
| 252 using namespace __debug __attribute__ ((strong)); | |
| 253 } | |
| 254 </pre></div><div class="sect4" lang="en" xml:lang="en"><div class="titlepage"><d
iv><div><h5 class="title"><a id="methods.coexistence.link"></a>Link- and run-tim
e coexistence of release- and | |
| 255 debug-mode components</h5></div></div></div><p>Because each component has a
distinct and separate release and | |
| 256 debug implementation, there are are no issues with link-time | |
| 257 coexistence: the separate namespaces result in different mangled | |
| 258 names, and thus unique linkage.</p><p>However, components that are defined and u
sed within the C++ | |
| 259 standard library itself face additional constraints. For instance, | |
| 260 some of the member functions of <code class="code"> std::moneypunct</code> retur
n | |
| 261 <code class="code">std::basic_string</code>. Normally, this is not a problem, bu
t | |
| 262 with a mixed mode standard library that could be using either | |
| 263 debug-mode or release-mode <code class="code"> basic_string</code> objects, thin
gs | |
| 264 get more complicated. As the return value of a function is not | |
| 265 encoded into the mangled name, there is no way to specify a | |
| 266 release-mode or a debug-mode string. In practice, this results in | |
| 267 runtime errors. A simplified example of this problem is as follows. | |
| 268 </p><p> Take this translation unit, compiled in debug-mode: </p><pre class="prog
ramlisting"> | |
| 269 // -D_GLIBCXX_DEBUG | |
| 270 #include <string> | |
| 271 | |
| 272 std::string test02(); | |
| 273 | |
| 274 std::string test01() | |
| 275 { | |
| 276 return test02(); | |
| 277 } | |
| 278 | |
| 279 int main() | |
| 280 { | |
| 281 test01(); | |
| 282 return 0; | |
| 283 } | |
| 284 </pre><p> ... and linked to this translation unit, compiled in release mode:</p>
<pre class="programlisting"> | |
| 285 #include <string> | |
| 286 | |
| 287 std::string | |
| 288 test02() | |
| 289 { | |
| 290 return std::string("toast"); | |
| 291 } | |
| 292 </pre><p> For this reason we cannot easily provide safe iterators for | |
| 293 the <code class="code">std::basic_string</code> class template, as it is prese
nt | |
| 294 throughout the C++ standard library. For instance, locale facets | |
| 295 define typedefs that include <code class="code">basic_string</code>: in a mixe
d | |
| 296 debug/release program, should that typedef be based on the | |
| 297 debug-mode <code class="code">basic_string</code> or the | |
| 298 release-mode <code class="code">basic_string</code>? While the answer could be | |
| 299 "both", and the difference hidden via renaming a la the | |
| 300 debug/release containers, we must note two things about locale | |
| 301 facets:</p><div class="orderedlist"><ol type="1"><li><p>They exist as shared s
tate: one can create a facet in one | |
| 302 translation unit and access the facet via the same type name in a | |
| 303 different translation unit. This means that we cannot have two | |
| 304 different versions of locale facets, because the types would not be | |
| 305 the same across debug/release-mode translation unit barriers.</p></li><li><p>T
hey have virtual functions returning strings: these functions | |
| 306 mangle in the same way regardless of the mangling of their return | |
| 307 types (see above), and their precise signatures can be relied upon | |
| 308 by users because they may be overridden in derived classes.</p></li></ol></div
><p>With the design of libstdc++ debug mode, we cannot effectively hide | |
| 309 the differences between debug and release-mode strings from the | |
| 310 user. Failure to hide the differences may result in unpredictable | |
| 311 behavior, and for this reason we have opted to only | |
| 312 perform <code class="code">basic_string</code> changes that do not require ABI | |
| 313 changes. The effect on users is expected to be minimal, as there are | |
| 314 simple alternatives (e.g., <code class="code">__gnu_debug::basic_string</code>
), | |
| 315 and the usability benefit we gain from the ability to mix debug- and | |
| 316 release-compiled translation units is enormous.</p></div><div class="sect4" la
ng="en" xml:lang="en"><div class="titlepage"><div><div><h5 class="title"><a id="
methods.coexistence.alt"></a>Alternatives for Coexistence</h5></div></div></div>
<p>The coexistence scheme above was chosen over many alternatives, | |
| 317 including language-only solutions and solutions that also required | |
| 318 extensions to the C++ front end. The following is a partial list of | |
| 319 solutions, with justifications for our rejection of each.</p><div class="itemi
zedlist"><ul type="disc"><li><p><span class="emphasis"><em>Completely separate d
ebug/release libraries</em></span>: This is by | |
| 320 far the simplest implementation option, where we do not allow any | |
| 321 coexistence of debug- and release-compiled translation units in a | |
| 322 program. This solution has an extreme negative affect on usability, | |
| 323 because it is quite likely that some libraries an application | |
| 324 depends on cannot be recompiled easily. This would not meet | |
| 325 our <span class="emphasis"><em>usability</em></span> or <span class="emphasis"
><em>minimize recompilation</em></span> criteria | |
| 326 well.</p></li><li><p><span class="emphasis"><em>Add a <code class="code">Debug
</code> boolean template parameter</em></span>: | |
| 327 Partial specialization could be used to select the debug | |
| 328 implementation when <code class="code">Debug == true</code>, and the state | |
| 329 of <code class="code">_GLIBCXX_DEBUG</code> could decide whether the | |
| 330 default <code class="code">Debug</code> argument is <code class="code">true</c
ode> | |
| 331 or <code class="code">false</code>. This option would break conformance with t
he | |
| 332 C++ standard in both debug <span class="emphasis"><em>and</em></span> release
modes. This would | |
| 333 not meet our <span class="emphasis"><em>correctness</em></span> criteria. </p>
</li><li><p><span class="emphasis"><em>Packaging a debug flag in the allocators<
/em></span>: We could | |
| 334 reuse the <code class="code">Allocator</code> template parameter of containe
rs | |
| 335 by adding a sentinel wrapper <code class="code">debug<></code> that | |
| 336 signals the user's intention to use debugging, and pick up | |
| 337 the <code class="code">debug<></code> allocator wrapper in a partial | |
| 338 specialization. However, this has two drawbacks: first, there is a | |
| 339 conformance issue because the default allocator would not be the | |
| 340 standard-specified <code class="code">std::allocator<T></code>. Second
ly | |
| 341 (and more importantly), users that specify allocators instead of | |
| 342 implicitly using the default allocator would not get debugging | |
| 343 containers. Thus this solution fails the <span class="emphasis"><em>correctn
ess</em></span> | |
| 344 criteria.</p></li><li><p><span class="emphasis"><em>Define debug containers
in another namespace, and employ | |
| 345 a <code class="code">using</code> declaration (or directive)</em></span>:
This is an | |
| 346 enticing option, because it would eliminate the need for | |
| 347 the <code class="code">link_name</code> extension by aliasing the | |
| 348 templates. However, there is no true template aliasing mechanism | |
| 349 is C++, because both <code class="code">using</code> directives and using | |
| 350 declarations disallow specialization. This method fails | |
| 351 the <span class="emphasis"><em>correctness</em></span> criteria.</p></li><
li><p><span class="emphasis"><em> Use implementation-specific properties of anon
ymous | |
| 352 namespaces. </em></span> | |
| 353 See <a class="ulink" href="http://gcc.gnu.org/ml/libstdc++/2003-08/msg00004.
html" target="_top"> this post | |
| 354 </a> | |
| 355 This method fails the <span class="emphasis"><em>correctness</em></span> cri
teria.</p></li><li><p><span class="emphasis"><em>Extension: allow reopening on n
amespaces</em></span>: This would | |
| 356 allow the debug mode to effectively alias the | |
| 357 namespace <code class="code">std</code> to an internal namespace, such | |
| 358 as <code class="code">__gnu_std_debug</code>, so that it is completely | |
| 359 separate from the release-mode <code class="code">std</code> namespace. Whil
e | |
| 360 this will solve some renaming problems and ensure that | |
| 361 debug- and release-compiled code cannot be mixed unsafely, it ensures that | |
| 362 debug- and release-compiled code cannot be mixed at all. For | |
| 363 instance, the program would have two <code class="code">std::cout</code> | |
| 364 objects! This solution would fails the <span class="emphasis"><em>minimize | |
| 365 recompilation</em></span> requirement, because we would only be able to | |
| 366 support option (1) or (2).</p></li><li><p><span class="emphasis"><em>Extensi
on: use link name</em></span>: This option involves | |
| 367 complicated re-naming between debug-mode and release-mode | |
| 368 components at compile time, and then a g++ extension called <span class="emp
hasis"><em> | |
| 369 link name </em></span> to recover the original names at link time. There | |
| 370 are two drawbacks to this approach. One, it's very verbose, | |
| 371 relying on macro renaming at compile time and several levels of | |
| 372 include ordering. Two, ODR issues remained with container member | |
| 373 functions taking no arguments in mixed-mode settings resulting in | |
| 374 equivalent link names, <code class="code"> vector::push_back() </code> being | |
| 375 one example. | |
| 376 See <a class="ulink" href="http://gcc.gnu.org/ml/libstdc++/2003-08/msg00177.
html" target="_top">link | |
| 377 name</a> </p></li></ul></div><p>Other options may exist for implementing the
debug mode, many of | |
| 378 which have probably been considered and others that may still be | |
| 379 lurking. This list may be expanded over time to include other | |
| 380 options that we could have implemented, but in all cases the full | |
| 381 ramifications of the approach (as measured against the design goals | |
| 382 for a libstdc++ debug mode) should be considered first. The DejaGNU | |
| 383 testsuite includes some testcases that check for known problems with | |
| 384 some solutions (e.g., the <code class="code">using</code> declaration solution | |
| 385 that breaks user specialization), and additional testcases will be | |
| 386 added as we are able to identify other typical problem cases. These | |
| 387 test cases will serve as a benchmark by which we can compare debug | |
| 388 mode implementations.</p></div></div></div><div class="sect2" lang="en" xml:la
ng="en"><div class="titlepage"><div><div><h3 class="title"><a id="manual.ext.deb
ug_mode.design.other"></a>Other Implementations</h3></div></div></div><p> | |
| 389 </p><p> There are several existing implementations of debug modes for C++ | |
| 390 standard library implementations, although none of them directly | |
| 391 supports debugging for programs using libstdc++. The existing | |
| 392 implementations include:</p><div class="itemizedlist"><ul type="disc"><li><p><
a class="ulink" href="http://www.mathcs.sjsu.edu/faculty/horstman/safestl.html"
target="_top">SafeSTL</a>: | |
| 393 SafeSTL was the original debugging version of the Standard Template | |
| 394 Library (STL), implemented by Cay S. Horstmann on top of the | |
| 395 Hewlett-Packard STL. Though it inspired much work in this area, it | |
| 396 has not been kept up-to-date for use with modern compilers or C++ | |
| 397 standard library implementations.</p></li><li><p><a class="ulink" href="http:/
/www.stlport.org/" target="_top">STLport</a>: STLport is a free | |
| 398 implementation of the C++ standard library derived from the <a class="ulink" h
ref="http://www.sgi.com/tech/stl/" target="_top">SGI implementation</a>, and | |
| 399 ported to many other platforms. It includes a debug mode that uses a | |
| 400 wrapper model (that in some way inspired the libstdc++ debug mode | |
| 401 design), although at the time of this writing the debug mode is | |
| 402 somewhat incomplete and meets only the "Full user recompilation" (2) | |
| 403 recompilation guarantee by requiring the user to link against a | |
| 404 different library in debug mode vs. release mode.</p></li><li><p><a class="uli
nk" href="http://www.metrowerks.com/mw/default.htm" target="_top">Metrowerks | |
| 405 CodeWarrior</a>: The C++ standard library that ships with Metrowerks | |
| 406 CodeWarrior includes a debug mode. It is a full debug-mode | |
| 407 implementation (including debugging for CodeWarrior extensions) and | |
| 408 is easy to use, although it meets only the "Full recompilation" (1) | |
| 409 recompilation guarantee.</p></li></ul></div></div></div><div class="navfooter"
><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align
="left"><a accesskey="p" href="bk01pt12ch30s03.html">Prev</a> </td><td width="20
%" align="center"><a accesskey="u" href="debug_mode.html">Up</a></td><td width="
40%" align="right"> <a accesskey="n" href="parallel_mode.html">Next</a></td></tr
><tr><td width="40%" align="left" valign="top">Using </td><td width="20%" align=
"center"><a accesskey="h" href="../spine.html">Home</a></td><td width="40%" alig
n="right" valign="top"> Chapter 31. Parallel Mode</td></tr></table></div></body>
</html> | |
| OLD | NEW |