Lifetime of static objects revisited


S

Simon Elliott

I have a C++ file which needs to work along these lines:

class foo
{
private:
int i1_;
public:
foo():i1_(12){}
~foo()
{
ExecuteSomething(); // Must be executed before program exits
}
int GetI1(void)const{return(i1_);}
void SetI1(int i1){i1_ = i1;}
};

static foo MyStaticFoo;

extern void f1()
{
MyStaticFoo.SetI1(13);
}

extern int f2()
{
return(MyStaticFoo.GetI1());
}

In other words, it needs to retain some state in a static object. On
program exit, the static object's destructor must be called.

Unfortunately, it seems that foo's destructor is (sometimes) being
called before some of the functions which need to access it.

How can I change this design so that foo is not destroyed until I'm
finished with it?

I can't change
static foo MyStaticFoo;
to
static foo* MyStaticFoo = 0;

and use dynamic allocation, because then someone will have to remember
to call delete on the object, and if they forget, the destructor won't
be called.

I don't think I can use a singleton pattern either, because I still
can't guarantee that the object won't be destroyed while I still need
it.

Any thoughts?
 
Ad

Advertisements

V

Victor Bazarov

Simon said:
I have a C++ file which needs to work along these lines:

class foo
{
private:
int i1_;
public:
foo():i1_(12){}
~foo()
{
ExecuteSomething(); // Must be executed before program exits
}
int GetI1(void)const{return(i1_);}
void SetI1(int i1){i1_ = i1;}
};

static foo MyStaticFoo;

extern void f1()
{
MyStaticFoo.SetI1(13);
}

extern int f2()
{
return(MyStaticFoo.GetI1());
}

In other words, it needs to retain some state in a static object. On
program exit, the static object's destructor must be called.

Unfortunately, it seems that foo's destructor is (sometimes) being
called before some of the functions which need to access it.

How can I change this design so that foo is not destroyed until I'm
finished with it?

I can't change
static foo MyStaticFoo;
to
static foo* MyStaticFoo = 0;

and use dynamic allocation, because then someone will have to remember
to call delete on the object, and if they forget, the destructor won't
be called.

I don't think I can use a singleton pattern either, because I still
can't guarantee that the object won't be destroyed while I still need
it.

Any thoughts?

Creating it dynamically and relying upon _not_ destroying it is basically
all you can do with current design.

If you can change the design, you can make the 'MyStaticFoo' a static
object of some base class of those classes that use it. Thus you can
ensure that it exists until the last object that needs it is destroyed.
IOW, rethink your design so you don't use global functions f1 and f2.

V
 
S

Simon Elliott

Creating it dynamically and relying upon not destroying it is
basically all you can do with current design.

If you can change the design, you can make the 'MyStaticFoo' a static
object of some base class of those classes that use it. Thus you can
ensure that it exists until the last object that needs it is
destroyed. IOW, rethink your design so you don't use global
functions f1 and f2.

Unfortunately I can't do this because it must fit into a legacy design.
However the foo object lifetime is bounded by a particular function so
I might be able to create an object which manages it...
 
V

Victor Bazarov

Simon said:
Unfortunately I can't do this because it must fit into a legacy design.
However the foo object lifetime is bounded by a particular function so
I might be able to create an object which manages it...

It could be the limitation of your "legacy design", of course, but if you
can, put the definition for your 'MyStaticFoo' in the same module as the
object that attempts to access it in the destructor (that's what causes
the problem, as I understand it) and place 'MyStaticFoo' _above_.

If you cannot due to aforementioned limitations, use the dynamic memory
approach, and rewrite the legacy stuff ASAP. Static initialisation fiasco
is a bitch and there is no way to fix it, only to avoid it.

V
 
R

Ricky Liu

Simon said:
I have a C++ file which needs to work along these lines:

class foo
{
private:
int i1_;
public:
foo():i1_(12){}
~foo()
{
ExecuteSomething(); // Must be executed before program exits
}
int GetI1(void)const{return(i1_);}
void SetI1(int i1){i1_ = i1;}
};

static foo MyStaticFoo;

extern void f1()
{
MyStaticFoo.SetI1(13);
}

extern int f2()
{
return(MyStaticFoo.GetI1());
}

In other words, it needs to retain some state in a static object. On
program exit, the static object's destructor must be called.

Unfortunately, it seems that foo's destructor is (sometimes) being
called before some of the functions which need to access it.

How can I change this design so that foo is not destroyed until I'm
finished with it?

I can't change
static foo MyStaticFoo;
to
static foo* MyStaticFoo = 0;

and use dynamic allocation, because then someone will have to remember
to call delete on the object, and if they forget, the destructor won't
be called.

I don't think I can use a singleton pattern either, because I still
can't guarantee that the object won't be destroyed while I still need
it.

Any thoughts?
It is the dead reference problem of the singleton pattern. As described
in the book Modern C++ Design by Andrei Alexandrescu, you can deal
with it in 3 ways:
1. Ignore it (which is not applicable in your case)
2. Recreate it (Phoenix Singleton)
3. Singletons with Longevity

Since MyStaticFoo keeps states, the 2nd choice is not applicable as well.
You can make use of the Loki library provided by the author for free.
You can download it by following the author's home page:
http://www.moderncppdesign.com/

Ricky
 
Ad

Advertisements

S

Simon Elliott

It is the dead reference problem of the singleton pattern. As
described in the book Modern C++ Design by Andrei Alexandrescu, you
can deal with it in 3 ways:
1. Ignore it (which is not applicable in your case)
2. Recreate it (Phoenix Singleton)
3. Singletons with Longevity

Since MyStaticFoo keeps states, the 2nd choice is not applicable as
well. You can make use of the Loki library provided by the author
for free. You can download it by following the author's home page:
http://www.moderncppdesign.com/

Thanks for this. I'm not familiar with the concept of "Singletons with
Longevity". Andrei Alexandrescu's book is refrred to so frequently that
I think it's time for me to buy a copy...
 
Ad

Advertisements


Top