|  | Singletons and destructors |  | |
| | | Rune Allnor |  |
| Posted: Thu Jul 24, 2008 1:23 am Post subject: Singletons and destructors |  |
| |  | |
Hi all.
I have struggled for a couple of days with a singleton pattern. It turned out that the cause of the problem is that the destructor of a singleton pattern is not called unless somebody calls a 'delete' to a pointer to the singleton.
Below is an example, where the program reports what methods it calls. The only way I can find to see a report from the singleton::destructor is to uncomment the 'delete' statement indicated.
This is a bit awkward, since there may be more than one refernece to the singleton, and it is not at all clear which refernce should be burdened with the responsibility to delet the singleton.
The obvious solution is to re-write the singleton pattern in terms of smart pointers. I don't want to reinvent the wheel, so is there a standard singleton pattern out there which uses smart pointers?
Rune
/////////////////////////////////////////////////////////////// //#include "stdafx.h" // Uncomment if you use visual studio #include <iostream>
class singleton{ public: static singleton* instance(); ~singleton(); protected: singleton(); private: static singleton* instance_; };
singleton* singleton::instance_=0; singleton::singleton() { std::cout << "In constructor" << std::endl; }
singleton::~singleton() { std::cout << "In destructor" << std::endl; }
singleton* singleton::instance() { std::cout << "In 'instance'" << std::endl; if (instance_ == 0) { instance_ = new singleton; } return instance_; }
int main(int argc,char* argv[]) { singleton* s = singleton::instance(); singleton* t = singleton::instance(); // delete t; // <<< === Uncomment to call destructor return 0; }
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Hrayr BABAJANYAN |  |
| Posted: Thu Jul 24, 2008 5:50 am Post subject: Re: Singletons and destructors |  |
| |  | |
{ Please don't quote the clc++m banner, removed. -mod }
On Jul 23, 8:23 pm, Rune Allnor <all...@tele.ntnu.no> wrote:
| Quote: | Hi all.
I have struggled for a couple of days with a singleton pattern. It turned out that the cause of the problem is that the destructor of a singleton pattern is not called unless somebody calls a 'delete' to a pointer to the singleton.
Below is an example, where the program reports what methods it calls. The only way I can find to see a report from the singleton::destructor is to uncomment the 'delete' statement indicated.
This is a bit awkward, since there may be more than one refernece to the singleton, and it is not at all clear which refernce should be burdened with the responsibility to delet the singleton.
The obvious solution is to re-write the singleton pattern in terms of smart pointers. I don't want to reinvent the wheel, so is there a standard singleton pattern out there which uses smart pointers?
Rune
/////////////////////////////////////////////////////////////// //#include "stdafx.h" // Uncomment if you use visual studio #include <iostream
class singleton{ public: static singleton* instance(); ~singleton(); protected: singleton(); private: static singleton* instance_;
};
singleton* singleton::instance_=0; singleton::singleton() { std::cout << "In constructor" << std::endl;
}
singleton::~singleton() { std::cout << "In destructor" << std::endl;
}
singleton* singleton::instance() { std::cout << "In 'instance'" << std::endl; if (instance_ == 0) { instance_ = new singleton; } return instance_;
}
int main(int argc,char* argv[]) { singleton* s = singleton::instance(); singleton* t = singleton::instance(); // delete t; // <<< === Uncomment to call destructor return 0;
}
|
Hello,
Well if you use the implementation of the singleton you provided the deletion of the instance can be made using the std::atexit.
#include <cstdlib> // std::atexit
class Singleton { public: static Singleton* instance() { if (instance_ = 0) instance_ = new Singleton();
return instance_; }
static void free() { delete instance_; }
protected: Singleton(); ~Singleton();
private: static Singleton* instance_; };
Singleton Singleton::instance_ = 0;
// ...
int main() { std::atexit(Singleton::free);
// ...
return 0; }
And the implementation that I prefer is the following (here you don't need to care about deletion of the instance - it will be deleted at the program exit (but you also will not have a control on the deletion of the instance).
class Singleton { public: static Singleton& instance() { static Singleton anInstance; // the ctor is being called only once (initialization of local static variable) return anInstance; }
protected: Singleton(); ~Singleton(); };
PS: you may be interested in more detailed discussion of this (well known problem), so I would refer books by Alexandresku, Mayers and Sutter (unfortunately I don't have them with me right now so I cannot tell you the chapters).
Kind regards, -- Hrayr
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | aman.c++ |  |
| Posted: Thu Jul 24, 2008 11:19 am Post subject: Re: Singletons and destructors |  |
| |  | |
On Jul 24, 6:23 am, Rune Allnor <all...@tele.ntnu.no> wrote:
| Quote: | Hi all.
I have struggled for a couple of days with a singleton pattern. It turned out that the cause of the problem is that the destructor of a singleton pattern is not called unless somebody calls a 'delete' to a pointer to the singleton.
Below is an example, where the program reports what methods it calls. The only way I can find to see a report from the singleton::destructor is to uncomment the 'delete' statement indicated.
This is a bit awkward, since there may be more than one refernece to the singleton, and it is not at all clear which refernce should be burdened with the responsibility to delet the singleton.
The obvious solution is to re-write the singleton pattern in terms of smart pointers. I don't want to reinvent the wheel, so is there a standard singleton pattern out there which uses smart pointers?
Rune
|
Rune, There's no one-size-fits-all pattern and making singleton destruction generic is especially non-trivial. Here are a few basic tips about singleton destruction. Think about the LIFETIME of your singleton. In many cases singletons persist for lifetime of the program. In those cases you need to think what needs to be cleaned up at program exit.
In the most trivial implementation where your singleton persists for the lifetime of program and is just consuming memory as a resource, you might be freed from the trouble of destroying it. In other cases you might need some cleanup/destruction at program exit or during program execution.
But the destruction should be responsibility of the singleton class (just as creation is). Clients of the singleton shouldn't ideally be deleting it.
regards, Aman Angrish
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Rune Allnor |  |
| Posted: Thu Jul 24, 2008 11:58 am Post subject: Re: Singletons and destructors |  |
On 24 Jul, 07:50, Hrayr BABAJANYAN <Hrayr.BABAJAN...@gmail.com> wrote:
| Quote: | { Please don't quote the clc++m banner, removed. -mod }
On Jul 23, 8:23 pm, Rune Allnor <all...@tele.ntnu.no> wrote:
I have struggled for a couple of days with a singleton pattern. It turned out that the cause of the problem is that the destructor of a singleton pattern is not called unless somebody calls a 'delete' to a pointer to the singleton. ... PS: you may be interested in more detailed discussion of this (well known problem), so I would refer books by Alexandresku, Mayers and Sutter (unfortunately I don't have them with me right now so I cannot tell you the chapters).
|
If would be very useful if somebody could come up with specific references. I've found some mentioning in Alxandrescu's "Modern C++ design".
Rune
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Greg Herlihy |  |
| Posted: Thu Jul 24, 2008 7:58 pm Post subject: Re: Singletons and destructors |  |
| |  | |
On Jul 23, 6:23 pm, Rune Allnor <all...@tele.ntnu.no> wrote:
| Quote: | Below is an example, where the program reports what methods it calls. The only way I can find to see a report from the singleton::destructor is to uncomment the 'delete' statement indicated.
This is a bit awkward, since there may be more than one refernece to the singleton, and it is not at all clear which refernce should be burdened with the responsibility to delete the singleton.
The obvious solution is to re-write the singleton pattern in terms of smart pointers.
|
Why call "new" to allocate the singleton in the first place? Wouldn't the more obvious solution be to avoid "new" and "delete" by having the singleton be statically - instead of dynamically - allocated? In fact, the "classic" singleton pattern takes such an approach:
#include <iostream>
class singleton { public: static singleton* instance(); ~singleton(); protected: singleton(); };
singleton::singleton() { std::cout << "In constructor" << std::endl; }
singleton::~singleton() { std::cout << "In destructor" << std::endl; }
singleton* singleton::instance() { static singleton instance_;
std::cout << "In 'instance'\n";
return &instance_; }
int main(int argc,char* argv[]) { singleton* s = singleton::instance(); singleton* t = singleton::instance();
// no delete singleton call }
Program Output:
In constructor In 'instance' In 'instance' In destructor
Greg
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Guest |  |
| Posted: Thu Jul 24, 2008 10:10 pm Post subject: Re: Singletons and destructors |  |
On Jul 24, 12:58 pm, Greg Herlihy <gre...@mac.com> wrote:
| Quote: | Why call "new" to allocate the singleton in the first place? Wouldn't the more obvious solution be to avoid "new" and "delete" by having the singleton be statically - instead of dynamically - allocated? In fact, the "classic" singleton pattern takes such an approach:
|
I'd suggest seeing the FAQ, and the static deinitialization order fiasco. As others have said in this thread, it's not a simple problem with a simple solution, especially in multithreaded environments.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Greg Herlihy |  |
| Posted: Fri Jul 25, 2008 1:44 am Post subject: Re: Singletons and destructors |  |
| |  | |
On Jul 24, 3:10 pm, JoshuaMaur...@gmail.com wrote:
| Quote: | On Jul 24, 12:58 pm, Greg Herlihy <gre...@mac.com> wrote:
Why call "new" to allocate the singleton in the first place? Wouldn't the more obvious solution be to avoid "new" and "delete" by having the singleton be statically - instead of dynamically - allocated? In fact, the "classic" singleton pattern takes such an approach:
I'd suggest seeing the FAQ, and the static deinitialization order fiasco. As others have said in this thread, it's not a simple problem with a simple solution, especially in multithreaded environments.
|
Anyone who follows your suggestion and reads the C++ FAQ - will learn that there is no such thing as the "static deinitialization order fiasco" in C++ (at least as far as the FAQ is concerned). After all, the destruction of static objects is well-defined (static objects are destroyed in the reverse order of their construction.)
Perhaps you are referring to what the FAQ calls C++'s "static - initialization- order" fiasco (in which the order that statically- allocated objects are initialized - is not always specified in C++). However, there is no such problem with the timing of the singleton's initialization in the sample program I posted. The singleton in that program is certain to be initialized the very first time instance() is called - which is exactly the same point of initialization as in the original program.
There are other ways to show that the sample program I posted is sound. Logically, if it is safe for the program to delete the singleton object before main() exits, then it must also be safe to delete that same singleton, at a later point - namely, after main() exits. The danger is deleting an object too early, there is no danger in deleting an object "too late". Furthermore, in a multithreaded environment, deleting the singleton object after main() exits (that is, after all the other threads have terminated), clearly makes the most sense.
Of course all of these points are purely academic - I could have simply pointed out that the singleton object is the only statically- allocated object in the program I posted. Whereas - a program would have to declare two or more statically-allocated objects - before it could even begin to have a problem with the order in which they are initialized.
Greg
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Guest |  |
| Posted: Fri Jul 25, 2008 8:40 am Post subject: Re: Singletons and destructors |  |
| |  | |
On Jul 24, 6:44 pm, Greg Herlihy <gre...@mac.com> wrote:
| Quote: | On Jul 24, 3:10 pm, JoshuaMaur...@gmail.com wrote:
On Jul 24, 12:58 pm, Greg Herlihy <gre...@mac.com> wrote:
Why call "new" to allocate the singleton in the first place? Wouldn't the more obvious solution be to avoid "new" and "delete" by having the singleton be statically - instead of dynamically - allocated? In fact, the "classic" singleton pattern takes such an approach:
I'd suggest seeing the FAQ, and the static deinitialization order fiasco. As others have said in this thread, it's not a simple problem with a simple solution, especially in multithreaded environments.
Anyone who follows your suggestion and reads the C++ FAQ - will learn that there is no such thing as the "static deinitialization order fiasco" in C++ (at least as far as the FAQ is concerned). After all, the destruction of static objects is well-defined (static objects are destroyed in the reverse order of their construction.)
|
LINK [10.14] Why doesn't the construct-on-first-use idiom use a static object instead of a static pointer?
Paraphrasing: The point is simple: if there are any other static objects whose destructors might use the singleton ans after ans is destructed, bang, you're dead. If the constructors of other singletons a, b and c use ans, you should normally be okay since the runtime system will, during static deinitialization, destruct ans after the last of those three objects is destructed. However if a and/or b and/or c fail to use ans in their constructors and/or if any code anywhere gets the address of ans and hands it to some other static object, all bets are off and you have to be very, very careful.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Rune Allnor |  |
| Posted: Fri Jul 25, 2008 6:07 pm Post subject: Re: Singletons and destructors |  |
| |  | |
On 24 Jul, 21:58, Greg Herlihy <gre...@mac.com> wrote:
| Quote: | On Jul 23, 6:23 pm, Rune Allnor <all...@tele.ntnu.no> wrote:
Below is an example, where the program reports what methods it calls. The only way I can find to see a report from the singleton::destructor is to uncomment the 'delete' statement indicated.
This is a bit awkward, since there may be more than one refernece to the singleton, and it is not at all clear which refernce should be burdened with the responsibility to delete the singleton.
The obvious solution is to re-write the singleton pattern in terms of smart pointers.
Why call "new" to allocate the singleton in the first place? Wouldn't the more obvious solution be to avoid "new" and "delete" by having the singleton be statically - instead of dynamically - allocated?
|
If it can be done - of course. How does the code you posted work? I can find only two declarations of 'static' in the whole code, the method singleton::instance() and the local variable inside singleton::instance(). Are those declarations enough to force the whole class go static? Please humor me as I 'think out loud' through the code:
If I understand things correctly, the local variable singleton::instance_ inside singleton::instance() will be allocated at the first call to singleton::instance(). The address of this variable is returned at first call. Since the variable is declared 'static' it will remain in global memory until program termination, when its destructor will automatically be called, since no call to 'new' was used.
Ah, since singleton::instance() is 'static' it is the same function handle/address/memory footprint/whatever the correct term might be, which is called every time, ensuring that it is the same local static copy of instance_ which is accessed every time... hey, all of a sudden the code starts to make sense!
[BTW, now would be a good time for somebody to correct me if my understanding of this scheme is flawed in any way...]
Is there a reference to this 'classic' singleton pattern somewhere? I based my suggestion on the recipe in Gamma & al.
Rune
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Jiang |  |
| Posted: Sun Jul 27, 2008 9:24 pm Post subject: Re: Singletons and destructors |  |
| |  | |
| Quote: | Is there a reference to this 'classic' singleton pattern somewhere? I based my suggestion on the recipe in Gamma & al.
|
For the above "Meyers-Singleton", please read "More Effective C++" by Scott Meyers. Sure you've read it, right? :-)
Singleton is a special pattern, here "special" means, it is quite easy to understand how it works at the first glance, but is extremely difficult to make it really work. Yes, as other said, there is no such a silver-bullet can solve all the problems.
Please have a look at Loki::Singleton at
LINK
, maybe it is not the singleton as you expected. :-)
So my suggestion is, well, check your targets carefully and find the necessary trade-offs to make the life easier. For example,
* If you can make sure you will not do mulit-threading in your program, then lock issues can be saved.
* If you can change your definition of "memory leak", then you do not have to delete the singleton in the heap, since most of the OS will handle this issue for you. (But this does not apply to other resource, such as GUI handles, .etc)
P.S. Please make sure you really need the Singleton, someone believes Singleton is an Anti-Pattern.
LINK LINK
You do not have to agree with it, but it is better to add these issues to your check-list, IMHO.
HTH
Jiang
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| Page 1 of 2 .:. Goto page 1, 2 Next | |
|
|