class Singleton
{
private:
static Singleton s;
Singleton(){}
public:
static Singleton *getInstance()
{
return &s;
}
};
Singleton Singleton::s;
Is this a valid singleton class?
class Singleton
{
private:
static Singleton *m_instance;
Singleton(){}
public:
static Singleton *getInstance()
{
return m_instance;
}
};
Singleton * Singleton::m_instance = new Singleton;
.
class Singleton
{
private:
static Singleton *m_instance;
Singleton(){}
public:
static Singleton *getInstance()
{
if(m_instance == NULL)
{
lock();
if(m_instance == NULL)
m_instance = new Singleton;
unlock();
}
return m_instance;
}
};
Singleton * Singleton::m_instance = NULL;
The three singleton classes above both are thread safe, but they are both prone to "static initialization order fiasco", am I right?
Is this a valid singleton class?
Now, after the edit the answer is yes, it is valid & it is also thread safe since all non-function-scope static variables are constructed before main(), while there is only one active thread.
C++ Standard n3337 § 3.6.2/1 § 3.6.2/2: Initialization of non-local variables
There are two broad classes of named non-local variables: those with
static storage duration (3.7.1) and those with thread storage duration
(3.7.2). Non-local variables with static storage duration are
initialized as a consequence of program initiation. Non-local
variables with thread storage duration are initialized as a
consequence of thread execution. Within each of these phases of initiation, initialization occurs as follows.
Variables with static storage duration (3.7.1) or thread storage
duration (3.7.2) shall be zero-initialized (8.5) before any other
initialization takes place. Constant initialization is performed:
— if each full-expression (including implicit conversions) that
appears in the initializer of a reference with static or thread
storage duration is a constant expression (5.19) and the reference is
bound to an lvalue designating an object with static storage duration
or to a temporary (see 12.2);
— if an object with static or thread storage duration is initialized
by a constructor call, if the constructor is a constexpr constructor,
if all constructor arguments are constant expressions (including
conversions), and if, after function invocation substitution (7.1.5),
every constructor call and full-expression in the mem-initializers and
in the brace-or-equal-initializers for non-static data members is a
constant expression;
— if an object with static or thread storage duration is not
initialized by a constructor call and if every full-expression that
appears in its initializer is a constant expression.
Together, zero-initialization and constant initialization are called
static initialization; all other initial- ization is dynamic
initialization. Static initialization shall be performed before any
dynamic initialization takes place. (...)
C++ Standard n3337 § 6.7/4: Declaration statement
The zero-initialization (8.5) of all block-scope variables with static
storage duration (3.7.1) or thread storage duration (3.7.2) is
performed before any other initialization takes place. Constant
initialization (3.6.2) of a block-scope entity with static storage
duration, if applicable, is performed before its block is first
entered. An implementation is permitted to perform early
initialization of other block-scope variables with static or thread
storage duration under the same conditions that an implementation is
permitted to statically initialize a variable with static or thread
storage duration in namespace scope. Otherwise such a variable is
initialized the first time control passes through its declaration;
such a variable is considered initialized upon the completion of its
initialization. If the initialization exits by throwing an exception,
the initialization is not complete, so it will be tried again the next
time control enters the declaration. If control enters the declaration
concurrently while the variable is being initialized, the concurrent
execution shall wait for completion of the initialization*). (...)
*):
The implementation must not introduce any deadlock around execution of
the initializer.
But it is still prone to static initialization order fiasco. The common way to write getInstance is:
Singleton& getInstance()
{
static Singleton instance;
return instance;
}
This way you can avoid this initialization problem.
Is this a thread-safe singleton class?
In C++11 above code is thread safe. In C++03 you can use
pthread_once
Besides this you should also prevent from copying and assignment:
Singleton( Singleton const&); // Don't Implement
void operator=( Singleton const&); // Don't implement
As far as I can tell, it's thread safe. But it's susceptible to static initialization order fiasco.
If an object tries to access Singleton in it's constructor and that object is constructed during program initialization and this code is in another compilation unit than Singleton, it may or may not crash because Singleton::s may or may not have been initialized yet (because the order of initialization of static objects across compilation units is undefined). Here is an example:
// in another compilation unit, far far away
struct Foo {
Foo() {
Singleton::getInstance();
}
};
Foo foo;
That's the lazy initialised Singleton, yes. It is thread safe under C++11.
Related
The code below supposedly initializes a static thread-local and static struct.
#include <iostream>
struct Tracer {
public:
Tracer(const char *new_name) : name{new_name} {
printf("%s : Constructor()\n", this->name);
}
~Tracer() {
printf("%s : Destructor()\n", this->name);
}
private:
const char *name;
};
// 1. Thread-Local Storage Duration
static thread_local Tracer t_thread_local{"Thread-Local Storage Duration"};
// 2. Static Storage Duration
static Tracer t_static{"Static Storage Duration"};
int main() {
printf("Start Program\n");
}
However, I don't see the message expected from the static thread-local struct Constructor/Destructor. The output printed only shows messages from the static struct. Am I missing something?
Static Storage Duration : Constructor()
Start Program
Static Storage Duration : Destructor()
Your assumption that merely declaring & defining these objects must assuredly trigger pre-main construction is incorrect.
[basic.stc.thread/2]: [ Note: A variable with thread storage duration is initialized as specified in [basic.start.static], [basic.start.dynamic], and [stmt.dcl] and, if constructed, is destroyed on thread exit ([basic.start.term]). — end note ]
[basic.start.dynamic/5]: It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized. [..]
There are in fact a number of similar rules in basic.start.dynamic.
Point is, your program doesn't do very much, and it certainly doesn't use t_thread_local, so it's up to the compiler as to whether t_thread_local will ever really exist and, if so, when.
I encountered this C++ static initialization order related query at a code review recently.
I've a class with static member variable in a compilation unit
I've a static object of that class using a constructor in a different compilation unit
Here, I want to know if the static member variable is guaranteed to be initialized before the static object constructor is called?
MyClass.h:
typedef int (*MyFunc)(int);
class MyClass {
MyClass(MyFunc fptr) {
mFunc = fptr;
}
static MyFunc mFunc;
}
MyClass.cpp:
MyFunc MyClass::mFunc = nullptr;
MyDifferentClass.h:
MyDifferentClass {
public:
static int MyStaticFunc(int);
}
MyDifferentClass.cpp:
static MyClass myClassObj(MyDifferentClass::MyStaticFunc);
In the code, would mFunc be initialized to nullptr before myClassObj gets created? The reason for the query is that if the order is not guaranteed, then mFunc may get initialized again to nullptr.
In the code, would mFunc be initialized to nullptr before myClassObj gets created? The reason for the query is that if the order is not guaranteed, then mFunc may get initialized again to nullptr.
The answer to the question is "Yes".
Setting aside the issue of initialization of thread specific objects, initialization of non-local variables is carried out in the following order.
All variables are zero-initialized (order not specified). This is called zero initialization.
All variables that can be initialized using constant values are initialized. This is called constant initialization.
Those ( 1 and 2 above) are called static initialization.
After that, dynamic initialization is performed.
In your case, MyClass::mFunc is initialized using constant initialization while myClassObj is initialized using dynamic initialization. Hence, the former is guaranteed to be initialized first.
More on this topic can be found at https://timsong-cpp.github.io/cppwp/n3337/basic.start.init.
How should I work with exceptions throwed from constructors of local static objects? For example I have following code:
class A
{
public:
A() {throw runtime_error("Ooops");}
};
void foo()
{
static A a = A();
cout << "Continue" << endl;
}
int main(void)
{
try
{
foo();
}
catch(...)
{
}
foo(); // Prints continue
return 0;
}
As I understand, in the case of second calling foo method, object a is treated as fully constructed object, and constructor is not called. (More over, it seems like destructor of a due first exception throwing is not called)
If that's true, then that is a compiler bug.
(However, VTT claims that this code produces the expected result with Visual Studio 2015, so I recommend double-checking your results.)
Here's the standard-mandated behaviour:
[C++14: 6.7/4]: The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered. An implementation is permitted to perform early initialization of other block-scope variables with static or
thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined. [..]
GCC 6.3.0 correctly attempts to reconstruct the A (and thus throws again).
More over, it seems like destructor of a due first exception throwing is not called
No, it won't be. You can't destroy an object that was never successfully created in the first place.
[C++14: 15.2/2]: An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.
By the way, this doesn't fix the problem, but you should just write:
static A a;
The copy-initialisation from a temporary is pointless.
Each instance of static local variable also implicitly creates a global Boolean variable that will be set to true after static variable is constructed. If constructor throws than the next time method is called there will be another attempt to construct a static variable.
I have done little work in multi-threaded environments. So, I need to know whether below class's getInstance function is thread-safe or not. Here is singleton class :
//Singleton class
class S {
// intentionally avoided pointer
static S singleObject;
// Private constructor
s ();
s (S &);
s& operator= (const s&);
public:
// return reference of static object
s& getInstance ()
{
return singleObject;
}
/* Normally with static pointer instance, getInstnace look like as
s& getInstace ()
{
// trying to avoid multiple copies of singleObject
lock_mutex ()
if (singleObject == null)
singleObjecct = new S();
unlock_mutex ();
return *singleObject;
}
*/
};
S S::singleObject;
In getInstance function (un-commented), static object's reference is returned. Does it requires thread-safe mechanism?
In second getInstance (commented), we create the object if singleObject is null. So, it requires a locking mechanism and needs to be synchronized, right?
In getInstance function (un-commented), static object's reference is returned. Does it requires thread-safe mechanism?
As long as you don't access it outside the lifetime of the main function, or modify it when other threads might have unsynchronised access, then it's safe to access from any thread.
If you do access before main starts or after it ends (e.g. from the constructor or destructor of another static object), then there is a danger that it won't have been initialised, or will already have been destroyed, at that point. That is the motivation for "lazy initialisation" such as your second version.
In second getInstance (commented), we create the object if singleObject is null. So, it requires a locking mechanism and needs to be synchronized, right?
Yes, that requires a locking mechanism. For compilers that support the C++11 (or similar) threading model, a simpler way to get lazy initialisation like this is to use a function-static variable, which will be initialised in a thread-safe way the first time it comes into scope:
S& getInstance ()
{
static S singleObject;
return singleObject;
}
This will also avoid the memory leak of your version, but introduces a danger that it might be destroyed before other static objects; therefore, it's not safe to access from a static object's destructor.
In general, static objects in C++ are a minefield of such deathtraps (whether or not you try to wrap them up in some kind of singleton anti-pattern) and are best avoided.
In C++11 you can place static instance inside a static function:
class S
{
private:
S();
S(S const&);
S& operator=(S const&);
public:
static S& getInstance ()
{
static S singleObject;
return singleObject;
}
};
According to paragraph 6.7.4 of the Standard:
The zero-initialization (8.5) of all block-scope variables with static
storage duration (3.7.1) or thread storage duration (3.7.2) is
performed before any other initialization takes place. Constant
initialization (3.6.2) of a block-scope entity with static storage
duration, if applicable, is performed before its block is first
entered. An implementation is permitted to perform early
initialization of other block-scope variables with static or thread
storage duration under the same conditions that an implementation is
permitted to statically initialize a variable with static or thread
storage duration in namespace scope (3.6.2). Otherwise such a variable
is initialized the first time control passes through its declaration;
such a variable is considered initialized upon the completion of its
initialization. If the initialization exits by throwing an exception,
the initialization is not complete, so it will be tried again the next
time control enters the declaration. If control enters the declaration
concurrently while the variable is being initialized, the concurrent
execution shall wait for completion of the initialization. If
control re-enters the declaration recursively while the variable is
being initialized, the behavior is undefined.
Unless you declare getInstance as static you won't be able to call it. This mistake has propagated almost to all replies. Other than this, I can't add anything better to all the answers.
IIRC this is better for more than this reason. It won't initialize (thread safely) until getInstance is called.
-edit- I remember some reasons now. You can't get access unless that method is called. You can call this in other class constructors and wont need to worry if S has been initialized or no. As in the other class may be constructed first in which case a crash or undefined behavior occurs.
//Singleton class
class S {
// intentionally avoided pointer
// Private constructor
s ();
s (S &);
s& operator= (const s&);
public:
// return reference of static object
s& getInstance ()
{
static S singleObject;
return singleObject;
}
};
I have a global object which is declared before main function and a static object inside main.
Which one of these uses (or do both?) static initialization?
I've heard that A obj1 is also called static; why is that?
class A { ... };
A obj1;
int main()
{
static A obj2;
}
obj1 has static storage. It will be initialized when the program starts.
obj2 also has static storage because you said so. It will be initialized when main() executes the first time.
My first doubt is how precise the question is. If static initailization is used with the technical meaning in the standard, it represents zero-initialization and initialization of a POD type with constant expressions for objects with storage duration, compared with dynamic initialization where the initialization of the object with static storage duration is initialized somehow else.
For an illustrative example:
// at namespace level
int f();
int a; // 1 static: zero initialization
int b = 10; // 2 static: initialization from constant expression
int c = f(); // 3 static (zero initialization)
// 5 followed by dynamic (result of call to f())
int d = 20; // 4 static: initialization
int f() { return d; }
int main() {}
The number indicates the order of execution of each initialization step. The reason why the compiler considers both static and dynamic initialization is that it sets an order on the execution of the initialization. static initialization is executed before dynamic initialization, and all statically initialized objects are guaranteed to have their value before any dynamic initialization starts. That is, the standard guarantees that even if d appears after c in the previous program, the value of c is guaranteed to be 20.
For objects that require dynamic initialization, they are (conceptually) zero initialized during static initailization, so during the lifetime of c, it is first set to 0, and later reset to f() (or 20 in this program). The conceptually is due to the fact that if the compiler can infer the final value that the variable will get, it can optimize the dynamic initialization away and just perform plain static initialization with that final value (in the above code, the compiler could detect that c is going to be dynamically initialized to 20, and decide to transform it into static initialization like int c = 20; in a conforming implementation. In that case steps 3 and 5 in the code above would be merged into a single step 3.
In the case of a local variable with static storage duration, the standard does not use the terms static/dynamic initialization, but the descriptions require the same behavior from the program. Local variables with static duration are zero-initialized or POD initialized with constant expressions when (or before) the block is entered for the first time (as with static initialization), while for the rest of the initializations are performed the first time that control passes over through it's declaration.
Focusing on C++ only, you also need to consider initialization of static members.
It concerns static members of a class.
For example, when you have:
class A {
// declaration of i as a static member of class A
static int i;
};
// initialization of static member outside class A
int A::i = 42;
Both of these variables are static:
obj1 is a non-local static variable which will be initialized when the program starts.
obj2 is a local static variable which will be initialised when the function is first called.
Scott Meyers in his book "Effective C++" recommends accessing local static variables through functions as opposed to using non-local static variables. Doing so avoids the so called static initialization order problem where one variable can reference another which may not have been initialized yet because of the arbitrary order in which initialization occurs.