[libstdc++ PATCH] libstdc++ debug mode (second try)

Doug Gregor dgregor@apple.com
Fri Jul 18 16:02:00 GMT 2003


This is my second attempt at the libstdc++ debug mode patch. Here is 
the capsule summary of the changes; read on for information on testing 
the patch.

	* No need to build/link against libstdc++-debug.
	* Merge __is_null_pointer back into basic_string.tcc (and
	removed gnu-cxx-utility.h).
	* Make macro naming scheme fit with libstdc++.
	* Added some missing copyright/license headers.
	* Move all debug-mode headers into include/debug/.
	* Release-mode debugging containers are now in __gnu_debug.
	* Necessary documentation updates.
	* Fixed a bug in _Safe_sequence::_M_invalidate_if.
	* Fix transfer of iterators in list::splice().
	* Add invalidation tests.

=== To test the patch ===
Apply this patch and also my link_name patch (attached, but will be 
submitted in full separately). No need to configure libstdc++ with 
--enable-libstdcxx-debug; just compile with -D_GLIBCXX_DEBUG.

=== Why no libstdc++-debug.(so|a)? ===
The first version of this patch built a separate library 
libstdc++-debug; executables compiled with the debug mode linked 
against this library in lieu of libstdc++. However, the two libraries 
could never be linked into the same program without causing serious 
trouble. This behavior is unfortunate and undesirable enough to push us 
to consider giving up a little on the checking side to make the debug 
mode easier to use.

What we gave up: safe iterators for std::basic_string<...>.

What we gained: the ability to mix debug-mode--compiled code with 
release-mode--compiled code, so long as one doesn't share an entity 
compiled with both debug and release modes.

==== Why no basic_string? ====
Most of the C++ standard library containers are user facilities only, 
and aren't reused in any other part of the library for any public 
interface. Strings, however, are pervasive, especially in locales. In 
locales, strings are used in the worst way possible from a 
debug/release-mode compatibility perspective: they are returned from 
virtual functions in a public interface. Since the debug mode operates 
by adding more information into containers & iterators (namely, 
references between the two), the size of std::basic_string needs to 
change from release to debug mode. However, with a virtual function 
returning a string, which string type is returned in a mixed 
debug/release program? (And remember that locales are part of the 
global state!). To further compound the problem, return types aren't 
part of the name-mangling scheme, so one won't even get a link error if 
the wrong string type is used.

To circumvent the problem, we chose to eliminate safe iterators for 
strings.

==== Mixing debug/non-debug code and the link_name patch ====
Even with the elimination of strings, we still have a problem with 
standard library types changing sizes in debug mode versus release 
mode. For instance, if we instantiate std::vector<int> in translation 
unit A compiled with debug mode and then instantiate std::vector<int> 
in translation unit B compiled with release mode, we have an ODR 
violation. But we want it to work, because it will help users, so we 
find a way to make the ODR violation _not_ cause real problems. There 
is no alias mechanism in C++ for templates, so both std::vector<int>'s 
really are std::vector<int> and will mangle the same way.

Enter link_name: the link_name patch introduces a new type attribute 
"link_name" that specifies a different name from the type name to use 
during name mangling. For instance, consider the following code:

   class __attribute__((__link_name__("bar"))) foo { };
   class bar { };

   void do_it(const foo&) { }
   void do_it(const bar&) { }

When we mangle the class "foo", it mangles with the name "bar" instead 
of foo. If one tries to compile this code, we'll get a duplicate 
definition error on do_it, because class foo (with link_name "bar") 
mangles in the exact same way as class bar does. We use this link_name 
trick to turn an ODR violation into something safer.

In release mode there are no link_name attributes, so std::list mangles 
as std::list. No change here from previous behavior.

In debug mode, we have both debug and release containers around, and 
std::list is the debug container. We note that the release container is 
exactly equivalent to the container in release mode. That's _very_ 
important. The two containers are:

	release container: the container name is prefixed with _Release_, so 
the std::list from release mode is named std::_Release_list in debug 
mode. However, the link_name attribute sets the link name to "list" to 
match what's in release mode. So from a linking perspective, the 
release-mode std::list and the debug-mode std::_Release_list are 
actually equivalent.

	debug container: the container name is retained (e.g., std::list), 
because this is the container the user sees. The link_name is then set 
to "_Debug_list", so it mangles differently from the release-mode 
container.

The code looks a little like this:

   template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
     class __attribute__((__link_name__("list"))) _Release_list { /* ... 
*/ };

   template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
     class __attribute__((__link_name__("_Debug_list"))) list
     : public _Release_list<_Tp, _Allocator>
     { /* ... */ };

Advantages of this scheme:
	* Debug/non-debug compatibility.
	* Link errors if one tries to link debug/non-debug units in an unsafe 
way.
	* Only one standard library.

Disadvantages of this scheme:
	* Don't have full checking of std::basic_string<...> in debug mode 
(but we may be able to get close!).
	* May be considered a hack.
	* In very rare circumstances (e.g., function returning a vector<int> 
but vector<int> otherwise unused in the translation unit), won't 
trigger link errors when debug/non-debug compatibility is abused.

=== Wrapup ===
Tested on i686-pc-linux-gnu and powerpc-apple-darwin; no regressions 
compiling libstdc++ testsuite in either debug mode or release mode on 
either platform. New iterator invalidation tests pass on both platforms 
in both debug mode and release mode.

Change log for the debug mode follows. The link_name change log will be 
submitted with the full link_name patch (later today, I hope).

	Doug

2003-07-18  Doug Gregor  <dgregor@apple.com>

         * Makefile.am: Optionally recurse into 'debug' subdir.
         * configure.in: Generate debug/Makefile.
         * docs/html/debug.html: Document libstdc++ debug mode.
         * docs/html/17_intro/howto.html: Document debug-mode macros.
         * include/Makefile.am: Install debug-mode headers.
         * src/Makefile.am: Include debug.cc.
         * include/bits/basic_string.tcc:
           (basic_string::_S_construct): Fix NULL pointer check.
           (__is_null_pointer): New.
         * include/bits/deque.tcc: Prefix class name with _Release_ when
         in debug mode.
         Mark the class as a release-mode class.
         * include/bits/istream.tcc: Ditto.
         * include/bits/list.tcc: Ditto.
         * include/bits/ostream.tcc: Ditto.
         * include/bits/stl_bvector.h: Ditto.
         * include/bits/stl_deque.h: Ditto.
         * include/bits/stl_list.h: Ditto.
         * include/bits/stl_map.h: Ditto.
         * include/bits/stl_multimap.h: Ditto.
         * include/bits/stl_multiset.h: Ditto.
         * include/bits/stl_set.h: Ditto.
         * include/bits/stl_vector.h: Ditto.
         * include/bits/vector.tcc: Ditto.
         * include/ext/hash_map: Ditto.
         * include/ext/hash_set: Ditto.
         * include/std/std_bitset.h: Ditto.
         * include/bits/stl_algo.h: Added algorithm precondition
         annotations.
         * include/bits/stl_algobase.h: Ditto.
         * include/ext/algorithm: Ditto.
         * testsuite/Makefile.am: Build a debug version of the testing
         support library.
         * testsuite/lib/libstdc++-v3-dg.exp: When compiling with
         -D_GLIBCXX_DEBUG, link against debug version of testing support
         library.
         * testsuite/23_containers/list_operators.cc: Don't verify
         performance guarantees when in debug mode.
         * testsuite/23_containers/bitset_inval.cc: New.
         * testsuite/23_containers/deque_inval.cc: New.
         * testsuite/23_containers/list_inval.cc: New.
         * testsuite/23_containers/map_inval.cc: New.
         * testsuite/23_containers/multimap_inval.cc: New.
         * testsuite/23_containers/multiset_inval.cc: New.
         * testsuite/23_containers/set_inval.cc: New.
         * testsuite/23_containers/vector_inval.cc: New.
         * include/debug/bitset: New.
         * include/debug/dbg_bitset.h: New.
         * include/debug/dbg_deque.h: New.
         * include/debug/dbg_hash_map.h: New.
         * include/debug/dbg_hash_multimap.h: New.
         * include/debug/dbg_hash_multiset.h: New.
         * include/debug/dbg_hash_set.h: New.
         * include/debug/dbg_list.h: New.
         * include/debug/dbg_map.h: New.
         * include/debug/dbg_multimap.h: New.
         * include/debug/dbg_multiset.h: New.
         * include/debug/dbg_set.h: New.
         * include/debug/dbg_vector.h: New.
         * include/debug/debug.h: New.
         * include/debug/deque: New.
         * include/debug/formatter.h: New.
         * include/debug/hash_map: New.
         * include/debug/hash_set: New.
         * include/debug/list: New.
         * include/debug/map: New.
         * include/debug/safe_base.h: New.
         * include/debug/safe_iterator.h: New.
         * include/debug/safe_iterator.tcc: New.
         * include/debug/safe_sequence.h: New.
         * include/debug/set: New.
         * include/debug/string: New.
         * include/debug/support.h: New.
         * include/debug/vector: New.
         * src/debug.cc: New.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: debugmode.patch.gz
Type: application/x-gzip
Size: 46743 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20030718/f2ee8b0b/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: linkname.patch
Type: application/octet-stream
Size: 6977 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20030718/f2ee8b0b/attachment.obj>


More information about the Gcc-patches mailing list