473,915 Members | 2,908 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

std::atexit

I am attempting to write a "Phoenix Singleton" using the book "Modern C++
Design" by Alexandrescu
I do not understand his use of...

#ifndef ATEXIT_FIXED
std::atexit(Kil l);
#endif

....in the source below. I understand the problem, but not how a preprocessor
directive will fix it. He says the standard is unclear about the situation
where one call to register with std::atexit is the result of is made as an
effect of another std::atexit registration. Can anyone be more specific on
how to fix the problem?

Source (forgive the indenting problems as a result of editor
incompatibiliti es):
// .h file
#ifndef SINGLETON_PHOEN IX
#define SINGLETON_PHOEN IX
#include "BaseException. h"
namespace cpisz_common_li b
{
//----------------------------------------------------------------------------------------------------------------------
/**
* Singleton_Pheon ix
*
* A singleton pattern that guarentees an instance will always be available.
*
*/
class Singleton_Phoen ix
{
public:
/**
* Retreives a reference to this singleton
*/
static Singleton_Phoen ix & GetInstance();
private:
static void Create();
static void Kill();
static void OnDeadReference ();
Singleton_Phoen ix();
Singleton_Phoen ix(const Singleton_Phoen ix &);
virtual ~Singleton_Phoe nix();
Singleton_Phoen ix & operator = (const Singleton_Phoen ix &);
static Singleton_Phoen ix * m_instance; // Pointer to the instance of this
object
static bool m_destroyed; // Flag that indicates the instance has been
destroyed
};
} // namespace cpisz_common_li b
#endif

// .cpp file
#include "Singleton_Phoe nix.h"
#include <cstdlib>
namespace cpisz_common_li b
{
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoen ix * Singleton_Phoen ix::m_instance = 0;
bool Singleton_Phoen ix::m_destroyed = false;
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoen ix & Singleton_Phoen ix::GetInstance ()
{
// Check if the object is instantiated
if( !m_instance )
{
// Check for dead reference
if( m_destroyed )
{
// Create a new instance, replacing the old destroyed instance
OnDeadReference ();
}
else
{
// Create the first instance
Create();
}
}
return *m_instance;
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoen ix::Create()
{
static Singleton_Phoen ix instance;
m_instance = &instance;
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoen ix::Kill()
{
// Set the instance pointer to NULL and destroyed flag to true;
m_instance->~Singleton_Pho enix();
}
//----------------------------------------------------------------------------------------------------------------------
void Singleton_Phoen ix::OnDeadRefer ence()
{
// Get the shell of the old reference to the instance
Create();
// Create a new instance at that same address
// Using the "placement new operator"
new(m_instance) Singleton_Phoen ix;
// Queue this new objects destruction
#ifndef ATEXIT_FIXED
std::atexit(Kil l);
#endif
// Reset the destoryed flag
m_destroyed = false;
}
//----------------------------------------------------------------------------------------------------------------------
Singleton_Phoen ix::~Singleton_ Phoenix()
{
m_instance = 0;
m_destroyed = true;
}
} // namespace cpisz_common_li b
Jan 2 '08 #1
2 4769
On Jan 2, 6:19 am, "Christophe r Pisz" <some...@somewh ere.netwrote:
I am attempting to write a "Phoenix Singleton" using the book
"Modern C++ Design" by Alexandrescu I do not understand his
use of...
#ifndef ATEXIT_FIXED
std::atexit(Kil l);
#endif
...in the source below. I understand the problem, but not how
a preprocessor directive will fix it. He says the standard is
unclear about the situation where one call to register with
std::atexit is the result of is made as an effect of another
std::atexit registration.
C99 is not unclear about this (although I seem to remember it
being undefined behavior in C90, and thus in C++98).
Can anyone be more specific on how to fix the problem?
Which problem? The code you posted has several different cases
of undefined behavior. All the #ifndef does is cause atexit not
to be called if ATEXIT_FIXED is defined.

I've not studied it in detail, but even after a quick glance, it
is apparent that if Kill() is ever called (and it will be called
if atexit is called), the destructor is called twice for the
same object. This is undefined behavior, and in a non-trivial
class, will almost certainly get you into trouble. So you
almost certainly have to defined ATEXIT_FIXED for the code to
work.

The obvious way to achieve the supposed goal (that an instance
will always be available) is to create the instance with new,
and never destruct it.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jan 2 '08 #2
On Jan 2, 6:02 am, James Kanze <james.ka...@gm ail.comwrote:
On Jan 2, 6:19 am, "Christophe r Pisz" <some...@somewh ere.netwrote:
[snip]
He says the standard is
unclear about the situation where one call to register with
std::atexit is the result of is made as an effect of another
std::atexit registration.

C99 is not unclear about this (although I seem to remember it
being undefined behavior in C90, and thus in C++98).
What does C99 say about it?
Can anyone be more specific on how to fix the problem?

Which problem? The code you posted has several different cases
of undefined behavior. All the #ifndef does is cause atexit not
to be called if ATEXIT_FIXED is defined.
That is what I suspected. If that is the case I don't see any reason
to put the preprocessor directive in there at all. I should always
execute that block.

I've not studied it in detail, but even after a quick glance, it
is apparent that if Kill() is ever called (and it will be called
if atexit is called), the destructor is called twice for the
same object. This is undefined behavior, and in a non-trivial
class, will almost certainly get you into trouble. So you
almost certainly have to defined ATEXIT_FIXED for the code to
work.
So, the code will not have undefined behavior if I remove the
preprocessor directive in that case? I do not see the other cases you
speak of even after examining the code in detail. The only problem I
can forsee is what happens at application exit when a registration
using std::atexit() is made as a result of another registration using
atexit(), which is the behavior my post is asking about. Anyone see
other cases of undefined behavior? Anyone have a definition of the
behavior mentioned?

The obvious way to achieve the supposed goal (that an instance
will always be available) is to create the instance with new,
and never destruct it.
I am unclear about this suggestion. If I new something and do not
delete it, is that not a memory and possibly a resource leak? What
will happen in the case that one of these singletons is dependent on
another at the time of application exit?

I am getting the feeling that what you are telling me is that this
book is out of date and there may be a better solution available. If
so, does anyone have a link? I have googled and found several
singleton implementations , but none of which seem to address the flaws
that this one is attempting to address.

I really want to try to avoid the authors proposal of implementing a
"dependency manager" and global "setlongevity(i nt)" methods. It seems
overly complex to me.
Jan 2 '08 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
4899
by: Siemel Naran | last post by:
Hi. I posted this question to comp.lang.c++, but am rephrasing it a bit from what I learned and posting to comp.lang.c++.moderated for more insight. So how do I solve my problem? I want it so that when the user presses Ctrl-C or eds the task from task manager (or the kill command in UNIX) then the system should shutdown gracefully. This means it should call the destructors of all objects, which means freeing dynamic memory, closing...
8
2847
by: JKop | last post by:
Let's say that when your program ends (no matter how) that you want a certain block of code to be executed at the end. Here's the code: std::cout << "The program will now end.\n"; std::system("PAUSE"); I've looked up "exit", "atexit" and "abort". Up until this point I simply would've done:
11
912
by: Jonan | last post by:
Hello, For several reasons I want to replace the built-in memory management with some custom built. The mem management itlsef is not subject to my question - it's ok to the point that I have nice and working allocation deallocation routines. However, I don't want to loose the nice extras of new operator, like - constructor calling, typecasting the result, keeping the array size, etc. For another bunch of reasons, outside this scope I...
5
1417
by: John Ratliff | last post by:
For code that was part of the C library, being used in C++, should you always prefix std:: Specific examples: std::fopen std::fclose std::atexit Should I include
11
3188
by: tomgee | last post by:
I saw it many times, // T.h: class T { public: static T* instance(); private: T() {}
12
1907
by: keepyourstupidspam | last post by:
Hi, I am writing a windows service. The code runs fine when I start the service when my machine is running but it fails to start automatically when the machine reboots. The code bombs out when it reaches code that tries to access a singleton class. This is the code.
7
6654
by: Adrian | last post by:
Hi, I have a large unmanaged static C++ library which I've wrapped using a small C++/CLR DLL. This is called from a C# client application. The static library has a singleton, however it appears that it is being instantiated twice. The first instantiation is down to me calling singleton.instance() in the C++/CLR DLL, the second instantiation is down to the library internally calling singleton.instance(). I'm relatively new to...
0
1231
by: Andreas Schmitt | last post by:
I am trying to get the PhoenixSingleton pattern example found in "Modern C++ Design" to run. I am using the Singleton in a DLL. I don't deliver any references of the Singleton to outside-DLL callers so that's not my problem. The singleton works perfectly, the only problem is.. after reviving the singleton, it doesn't get destroyed, meaning the destructor is not called. I checked that by using the DLL in a simple test application and...
0
9880
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
11352
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10922
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
11064
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9730
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6143
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4777
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4343
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3367
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.