Boost logo

Boost :

From: Chris Newbold (Chris.Newbold_at_[hidden])
Date: 2008-07-08 16:17:32


> From: boost-bounces_at_[hidden] [mailto:boost-bounces_at_[hidden]]
> On Behalf Of Phil Bouchard
> Sent: Tuesday, July 08, 2008 1:46 AM

> "Chris Newbold" <Chris.Newbold_at_[hidden]> wrote in message
> news:6F6A2FC198A0F943ACC2259C38A2E30B6688EDD1B4_at_EXCHANGE-
> AH.ad.mathworks.com...
>
> [...]
>
> > Just for grins, try printing a message out from the destructor of
> > owned_base::pool (or setting a breakpoint there) and see how many times
> > you wind up there. My hunch is that this is an ODR issue...
>
> I get the following:

...

> BTW I have gotten the same problem by using Gcc 4.3 and I am not linking
> multiple source files. Here is my build process:
> $ g++ shifted_ptr_test2.cpp -I ../../..

I've been able to reproduce this failure in my local sandbox, using GCC 4.1.2. My initial ODR hypothesis was not right, but was close: we're having a static-initialization ordering issue.

Pool's fast_pool_allocator class uses singleton_pool to manage a single underlying pool based on the requested size. Singleton_pool in turn uses singleton_default (found in pool/detail/singleton.hpp) which tries _really_ hard to force the compiler to construct the controlled instance at just the right time.

What's happening in your test case is that the namespace-scoped owned_base::pool instance (line 187 in sh_owned_base_nt.hpp) is actually being constructed by the compiler _before_ the namespace-scoped initializer object (called create_object, at line 95 in pool/detail/singleton.hpp). That in turn results in the compiler destructing the singleton pool _before_ destructing your owned_base::pool instance. Thus the memory containing the list nodes of the two std::list instanced contained in owned_base::pool is has been freed by the time the list destructors run.

I'm a little hard-pressed to make a call as to whether the problem is with GCC's initialization ordering or whether the "cleverness" in pool/detail/singleton.hpp is simply bankrupt and is trying to guarantee something which the language standard cannot.

The namespace-scoped initializer generated in pool/detail/singleton.hpp lexically precedes the declaration of the client in sh_owned_base_nt.hpp. Since this test case is a single translation unit, this should in theory ensure that the former is constructed before the latter. However, there's some indirection and function-scoped static objects in play here, too, which may render that guarantee meaningless.

I'd be interested to get some additional eyes on the code in pool/detail/singleton.hpp (there's a decent comment there about how it's supposed to work) and see if there can be a reasonable expectation for it to work on a conforming compiler...

-Chris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk