Static initialization order fiasco with smart pointers

B

Boris

I've a class C with a smart pointer (I use boost::shared_ptr) which is
initialized in the constructor:

class C {
boost::shared_ptr<D> d;
public:
C() : d(new d()) { }
};

When the program starts class C is instantiated quite a lot. As all the
instances of C use the same empty instance of D I want them to share the
instance:

class C {
boost::shared_ptr<D> d;
static boost::shared_ptr<D> one;
public:
C() : d(one) { }
};

boost::shared_ptr<D> C::eek:ne(new d());

That would work if I wasn't using the quick_allocator for boost::shared_ptr
(a memory manager which is used when BOOST_SP_USE_QUICK_ALLOCATOR is
defined). Now as it turns out this memory manager uses static variables.

According to the FAQ we initialize the static member now in a method:

class C {
boost::shared_ptr<D> d;
static boost::shared_ptr<D> one;
public:
C() : d(one) { }
static Init() { one.reset(new d()); }
};

boost::shared_ptr<D> C::eek:ne;

Now everything works until the program ends. If the static variables in the
memory manager of boost::shared_ptr are destroyed first the destructor of
the static smart pointer in class C will make a call to a non-existing
memory manager.

The only solution I see is freeing the static smart pointer when the last
instance of class C is destroyed (then noone needs the instance of D in the
smart pointer anymore). The destructor uses the counter of the smart pointer
to check when it should be freed:

class C {
boost::shared_ptr<D> d;
static boost::shared_ptr<D> one;
public:
C() : d(one) { }
static Init() { one.reset(new d()); }
~C() { if (one.unique()) one.reset(); }
};

boost::shared_ptr<D> C::eek:ne;

This is however no general solution (eg. if you destroy all instances of C
and then create a new one in the middle of the program the smart pointer is
empty). Is there a better idea how to handle this?

Boris
 
B

Boris

Boris said:
[...] This is however no general solution (eg. if you destroy all
instances
of C and then create a new one in the middle of the program the smart
pointer is empty). Is there a better idea how to handle this?

Alright, about three seconds after clicking on Send I suddenly understood
that the smart pointer must be created dynamically:

class C {
boost::shared_ptr<D> d;
static boost::shared_ptr<D> *one;
public:
C() : d(*one) { }
static Init() { one = new boost::shared_ptr<D>(new d()); }
};

boost::shared_ptr<D> *C::eek:ne;

Sometimes it helps to send a question just to find the answer yourself. :)

Boris
 
V

Victor Bazarov

Boris said:
Boris said:
[...] This is however no general solution (eg. if you destroy all
instances
of C and then create a new one in the middle of the program the smart
pointer is empty). Is there a better idea how to handle this?

Alright, about three seconds after clicking on Send I suddenly
understood that the smart pointer must be created dynamically:

class C {
boost::shared_ptr<D> d;
static boost::shared_ptr<D> *one;
public:
C() : d(*one) { }
static Init() { one = new boost::shared_ptr<D>(new d()); }

static *WHAT* Init()? Did you mean to say

static void Init()

???
};

boost::shared_ptr<D> *C::eek:ne;

This is initialised to a null pointer (since it's "static"). Is that
really what you wanted? As soon as I try creating an instance of 'C',
I get undefined behaviour because a null pointer is dereferenced...
Sometimes it helps to send a question just to find the answer
yourself. :)

No doubt. Did you actually find the answer?

V
 
B

Boris

Victor said:
[...] static *WHAT* Init()? Did you mean to say

static void Init()

???

Sorry, I forgot the return type.
This is initialised to a null pointer (since it's "static"). Is that
really what you wanted? As soon as I try creating an instance of 'C',
I get undefined behaviour because a null pointer is dereferenced...

Read my original message again and then the FAQ. Here's the direct link:
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14
No doubt. Did you actually find the answer?

Guess for what Init() is used for you corrected above?

Boris
 
V

Victor Bazarov

Boris said:
Victor said:
[...] static *WHAT* Init()? Did you mean to say

static void Init()

???

Sorry, I forgot the return type.
This is initialised to a null pointer (since it's "static"). Is that
really what you wanted? As soon as I try creating an instance of
'C', I get undefined behaviour because a null pointer is
dereferenced...

Read my original message again and then the FAQ. Here's the direct
link: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14
No doubt. Did you actually find the answer?

Guess for what Init() is used for you corrected above?

I don't see it called anywhere.

V
 
F

Fei Liu

Boris said:
Boris said:
[...] This is however no general solution (eg. if you destroy all
instances
of C and then create a new one in the middle of the program the smart
pointer is empty). Is there a better idea how to handle this?

Alright, about three seconds after clicking on Send I suddenly understood
that the smart pointer must be created dynamically:

class C {
boost::shared_ptr<D> d;
static boost::shared_ptr<D> *one;
public:
C() : d(*one) { }
static Init() { one = new boost::shared_ptr<D>(new d()); }
};

boost::shared_ptr<D> *C::eek:ne;

Sometimes it helps to send a question just to find the answer yourself. :)

Boris

Try the following code:

#include <iostream>
#include <boost/shared_ptr.hpp>

struct D {
int x;
D():x(3){}
};

class C {
boost::shared_ptr<D> d;
public:
C(): d(Init()) {}
static boost::shared_ptr<D> Init(){
static boost::shared_ptr<D> *one;
if(!one)
one = new boost::shared_ptr<D>(new D());
return *one;
}
void print(){
std::cout << "D::x = " << d->x << std::endl;
}
};

int main(void){

C c;
c.print();
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top