Article View: comp.std.c++
Article #3512Re: Destruction of singletons
From: James Kanze US/ESC 60/3/141 #407...
Date: Mon, 26 Feb 1996 19:50
Date: Mon, 26 Feb 1996 19:50
136 lines
7596 bytes
7596 bytes
In article <4go9au$l8f@engnews1.Eng.Sun.COM> Jamshid Afshar
<jamshid@IO.COM> writes:
|> In article <4fvng1$jit@netlab.cs.rpi.edu>,
|> Bob Archer <bob@hottub.demon.co.uk> wrote:
|> >Singleton * Singleton::Instance() {
|> > if (_instance == 0)
|> > _instance = new Singleton;
|> > return _instance;
|> >}
|> >
|> >[Jamshid] suggested that using a static local variable might be better:
|> >
|> >Singleton * Singleton::Instance() {
|> > static Singleton s;
|> > return &s;
|> >}
|> >
|> >James Kanze then replied:
|> > Although I tend to prefer this idiom too, it is important to realize
|> > that there are some cases where it is preferable *not* to destruct the
|> > variable. (If there is only one, this shouldn't constitute a memory
|> > leak.) [...]
|> >
|> >Why does the fact that only one variable is involved mean that this is
|> >not a memory leak?
|> James has responded that although technically it is a memory leak,
|> it's not important unless you're using a poor operating system that
|> does not recover all memory when a process finishes. I agree I
|> wouldn't want to use such an operating system (Win3.1?), but I think
|> it is sloppy programming to not ensure all the objects you create get
|> destroyed and all the memory you allocate gets deleted. Of course
|> there are probably cases where this is not possible or practical, but
|> leaked memory and undestroyed objects cause hassles when using
|> debugging tools like Purify which report all memory leaks when the
|> program finishes. You'll get enough leak reports from sloppy 3rd
|> party libraries -- you shouldn't be adding a bunch "ignore this leak,
|> I 'know' it's okay" configuration statements for the code you write.
|> Also, you may sometime soon want to remove the "singleton" restriction
|> on the class -- IMO get it right the first time and make sure its
|> destructor works properly.
First of all, I will agree that not destructing the object is not the
most elegant solution around, and in fact, now that I am aware of
relatively simple programming techniques (returning the address of a
local static) to ensure this, I use them.
Concerning the two practical objections, however:
1. As long as there is an active pointer to the memory (a static
pointer), Purify will not classify it as a leak.
2. This technique is only used for *static* data member pointers. If
the class is no longer used as a singleton, then it is no problem
putting the delete in the constructor. The problem is where to put
the delete otherwise. How can you know that everyone has finished
using the object.
In general, I would stress that the prefered solution is to not use
the singleton object in any destructors, and use a local static to
initialize the pointer. If you do have to use the object in
destructors, however, I would still prefer not destructing it to
trying to manage the `order of destruction' problem (given that most
compiler implementors still consider the order of destruction of
static locals undefined).
|> >I take the point about the Singleton object possibly being used in the
|> >destructors of a static object. Is there any way to ensure that the
|> >singleton will be destroyed but only after everything that might wish
|> >to use it has been destroyed ? (I guess that this is just the usual
|> >problem with the order of global construction / destruction ).
|> Actually, the construction and destruction of "local objects of static
|> storage duration" is not the same as objects outside of functions. In
|> fact, it seems local statics are more poorly specified. According to
|> the April '95 Draft, while they are guaranteed to not be constructed
|> until (and if) the function is called, exactly when the destructor is
|> called is unspecified.
I actually believe that it is, and in fact, has been well defined from
the ARM. The exact language in the sections concerning the
initialization and destruction of statics is significant: in the
sections concerning initializations, the reference is consistently to
`non-local' statics, whereas in the section concerning destruction,
the words `non-local' are significantly absent. IMHO, the extreme
care concerning the use of `non-local' in the initialization section
makes it clear that its absense in the destruction section was not
simply oversight, and that *all* statics were meant.
The perennial test suite contains a case which in fact does test this.
Regretfully, the compiler implementors I'm familiar with have all
denied that this was what was meant, and claimed that there was no
guarantee concerning local statics.
In any case, the Jan. 96 draft makes the question moot, since it
explicitly adds the words in the destructor section clarifying that
static means both local and non-local.
|> At least globals are sensibly guaranteed to be
|> destroyed in the reverse order they were constructed. What should
|> have been required IMO is that local statics be destroyed in the
|> reverse order they were (fully) constructed. For example, if the
|> constructor of a local static "g_list" calls a function containing
|> another local static "g_log", g_list should be destroyed first since
|> its construction was finished last. This is desirable behavior since
|> g_list's destructor may also use g_log.
I agree. The remaining weak point in the standard is that it doesn't
really specify what is meant by the ordering, entering the
constructor, or leaving it.
[...]
|> Is there any reason the committee chose not to have local statics do
|> this kind of ordering automatically? Of course, it won't solve every
|> problem related to "global" construction/destruction ordering, but it
|> seems a lot better than leaving it unspecified and doesn't seem like
|> it would have placed any burden whatsoever on implementors.
It does place a burden on the implementors, since in fact, the order
of destruction will depend upon the order the functions are called.
But the committe, and Bjarne before them, voted in favor of the
programmer, not the implementor.
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils, études et réalisations en logiciel orienté objet --
-- A la recherche d'une activité dans une region francophone
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Technical Details
Message-ID:
<9602261828.AA28873@lts.sel.alcatel.de>Path:
arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austernReferences:
<4fvng1$jit@netlab.cs.rpi.edu> <4go9au$l8f@engnews1.Eng.Sun.COM>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!chronicle.mti.sgi.com!austern From: James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de> Newsgroups: comp.std.c++ Subject: Re: Destruction of singletons Date: 26 Feb 1996 11:50:36 PST Organization: - Approved: austern@isolde.mti.sgi.com Message-ID: <9602261828.AA28873@lts.sel.alcatel.de> References: <4fvng1$jit@netlab.cs.rpi.edu> <4go9au$l8f@engnews1.Eng.Sun.COM> NNTP-Posting-Host: isolde.mti.sgi.com X-Original-Date: Mon, 26 Feb 96 19:28:57 +0100 In-Reply-To: Jamshid Afshar's message of 25 Feb 1996 00:09:02 GMT X-Auth: PGPMoose V1.1 PGP comp.std.c++ iQBVAwUBMTIPHUy4NqrwXLNJAQHKJAH9GAtsvu8gaLyjrUEw2C073PfxqKVy/t54 LrkuWJLDN+dN7kYUSo+GSVr0cirt95iSwjxg8au5um62NulSVn9YRA== =bYxj Originator: austern@isolde.mti.sgi.com