By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,948 Members | 852 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,948 IT Pros & Developers. It's quick & easy.

Static initialization order fiasco with smart pointers

P: n/a
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::one(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::one;

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::one;

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
Apr 13 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Boris wrote:
[...] 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::one;

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

Boris
Apr 13 '06 #2

P: n/a
Boris wrote:
Boris wrote:
[...] 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::one;
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 13 '06 #3

P: n/a
Victor Bazarov wrote:
[...] static *WHAT* Init()? Did you mean to say

static void Init()

???


Sorry, I forgot the return type.
boost::shared_ptr<D> *C::one;


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-lit...html#faq-10.14
Sometimes it helps to send a question just to find the answer
yourself. :)


No doubt. Did you actually find the answer?


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

Boris
Apr 13 '06 #4

P: n/a
Boris wrote:
Victor Bazarov wrote:
[...] static *WHAT* Init()? Did you mean to say

static void Init()

???


Sorry, I forgot the return type.
boost::shared_ptr<D> *C::one;


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-lit...html#faq-10.14
Sometimes it helps to send a question just to find the answer
yourself. :)


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
--
Please remove capital As from my address when replying by mail
Apr 14 '06 #5

P: n/a

Boris wrote:
Boris wrote:
[...] 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::one;

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();
}

Apr 19 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.