libstdc++ debug mode ideas 3

Benjamin Kosnik bkoz@redhat.com
Wed Aug 6 19:29:00 GMT 2003



Begin forwarded message:

Date: Wed, 30 Jul 2003 11:30:39 -0700
From: Doug Gregor <dgregor@apple.com>
To: Gabriel Dos Reis <gdr@integrable-solutions.net>
Cc: Benjamin Kosnik <bkoz@redhat.com>
Subject: Re: [libstdc++ PATCH] libstdc++ debug mode (second try)


On Wednesday, July 30, 2003, at 10:21AM, Gabriel Dos Reis wrote:
> | The fact is that, in the absence of a perfect template aliasing 
> model,
> | compiling part of a program in release mode and part of it in debug
> | mode is an ODR violation. If you agree with this, then I only see two
> | options:
> | 	(1) Find that perfect template aliasing model, or
> | 	(2) Manage the ODR violation so that it can't cause trouble.
>
> I do not think it is a template aliasing model and that finding that
> template alising model makes the problem (if there is one) go away.
>
> The template-name is primarily there to provide name commonality.
> What is being violated is not the declaration of the template-name,
> but the ODR for the entity being named by the template.

I think a perfect template aliasing model would make the problem go 
away because we could do this:

namespace std {
   namespace __release {
     template<typename T, typename Allocator = std::allocator<T> >
       class vector; // define release-mode vector
   }
   namespace __debug {
     template<typename T, typename Allocator = std::allocator<T> >
       class vector; // define debug-mode vector
   }
}

Then, we add some directive that makes std::vector alias 
std::__release::vector (when we're in release mode) or 
std::__debug::vector (when we're in debug mode). A using declaration 
very nearly gets us there, except that it breaks specialization:

namespace std {
#ifdef _GLIBCXX_DEBUG
   using __debug::vector;
#else
   using __release::vector;
#endif
}

  I think your template aliasing proposal would let us do this:

namespace std {
#ifdef _GLIBCXX_DEBUG
   template<typename T, typename Allocator=std::allocator<T> >
     using vector = __debug::vector<T, Allocator>;
#else
   template<typename T, typename Allocator=std::allocator<T> >
     using vector = __release::vector<T, Allocator>;
#endif
}

> | 	I see that include <debug/vector> makes std::vector the debug
> | version even if we are compiling in release mode.
>
> I must confess my sympathy for this approach.  It is the most simple
> semantics I would expect.

Okay. We're trading off the ability to easily switch a particular 
container instance to debug mode (e.g., by changing std::vector<...> to 
__gnu_debug::vector<...> in the source) with the ability to change all 
containers to debug versions (e.g., by including <debug/vector> instead 
of <vector>). I personally think the former is more important, because 
I suspect that users would prefer to debug programs that crash, say, 
after an iterator dereference by turning debugging on only for a few 
suspect container instances and compiling only a little code. The 
<debug/vector> model will turn on debugging for a lot more container 
instances, and I wonder how much use it would get vs. just turning on 
_GLIBCXX_DEBUG.

> | This differs from my
> | original patch, where <debug/vector> declares a debugging vector as
> | __gnu_debug::vector (regardless of whether or not we're in debug
> | mode). The benefit of your approach is that users can change one
> | #include to get debugging for a certain container type; the
> | disadvantage is that you can't change it for a single container
> | instance (since there is no separate __gnu_debug::vector to use). The
> | other issue is that
> |
> | 	#include <vector>
> | 	#include <debug/vector>
> |
> | will fail to compile in release mode, because std::vector will be
> | defined twice and __std::vector will not be defined at all. With this
> | methodology, the best we could do would be to emit a warning that the
> | debug-mode vector will _not_ be used, and then skip the debug
> | version. I wonder how many users would leave a stray <debug/vector>
> | somewhere in their program and wonder why things are running slowly.
>
> I think we should simply take that, we should avoid inclusion order
> dependency and we should avoid second-guessing the programmer, by
> assuming that he is stupid.  I'm not sure how we can reconsile the
> above criteria but I will certainly object to changing the semantics
> behind the back of the user.

Any idea on how we can avoid the inclusion-order dependencies? If we 
see both <debug/vector> and <vector>, so we always pick the debug 
version? The release version? AFAICT, we're stuck with the first one 
that's included (because it defines std::vector), and I think that's a 
bit confusing.

	Doug



More information about the Libstdc++ mailing list