From Scott Meyers Effective C++:
if you never call a function emulating a non-local static object, you
never incur the cost of constructing and destructing the object,
something that can’t be said for true non-local static objects.
The function:
FileSystem& tfs()
{
static FileSystem fs;
return fs;
}
But the Standard said:
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).
That means that we can't say for sure if the fs variable is or is not initialized even if we don't call to the function tfs(). Because implementation is permitted to perform early initialization as for variables with static storage duration.
Who was right or what did I miss?
Constant initialization describes initialization that can be determined at compile-time.
Only in C++11 and later can a type with a non-trivial constructor be considered:
if the constructor is constexpr
In "Effective C++", Meyers describes the class in your question literally as:
class FileSystem {...};
This would imply that given the C++ Standard being correct, "Effective C++" can also remain correct even after C++11 as long as the supplied constructor for FileSystem is not constexpr.
Related
Overarching question is: how can a programmer make sure that his non-local static variables are initialized via static initialization and not via dynamic initialization?
As zero-initialization is done always then one should look at the constant initialization.
3.6.2.2 A constant initializer for an object o is an expression that is a constant expression, except that it may also invoke constexpr
constructors for o and its subobjects even if those objects are of
non-literal class types [ Note: such a class may have a non-trivial
destructor —end note ]. 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, and if the initialization full-expression is a
constant initializer for the object;
— if an object with static or thread storage duration is not
initialized by a constructor call and if either the object is
value-initialized or every full-expression that appears in its
initializer is a constant expression.
I omitted the reference as it is not important in my case. How I understand the standard is that there are 3 cases:
ctor
no-ctor and value initialization
no-ctor and constant expression
Let's say I have a following class:
struct X {
bool flag = false;
// = {} will break VS2013 CTP so in that case use the
// regular ctor, which sadly still can't be declared constexpr
std::aligned_storage<sizeof(int), alignof(int)>::type storage = {};
};
As far as I can say this class is perfectly valid for constant initialization (each element can be constantly initialized). Is this true?
Does this class require a constexpr constructor?
Is constant initialization guaranteed for C++11 as well as C++98?
Side question: When will the static initialization done in case of so/dll? During the load time, or it might be delayed even further?
It would be good to know the purpose behind this question. And also whether your concern is allocation or specifically initialization.
However, the type of initialization shouldn't matter because the required space is allocated at compile time. Depending on how you define the variable, it will end up either in .bss or .data section.
Initialization, as you know, is only to ensure a specific content in the memory before it is first used. If you do not define a constructor that allocates dynamic memory then there won't be any dynamic allocation (if that is your concern).
For simple constructors, I believe the compiler will generate inline code and use the same to initialize the object at compile time (I am not sure what the standard talks about the same but it is possible that it is tool chain dependent.) With complex constructors, non-local static objects will be initialized when the image is loaded in memory and local static objects will be initialized when the stack frame is loaded. In any cases you should find the object in a known state before first use.
Side question: When will the static initialization done in case of
so/dll? During the load time, or it might be delayed even further?
On Windows, static initialization occurs before before DllMain() is invoked with the DLL loader lock acquired. This severely limits what you can do in the constructors for your static objects. You can't load any other DLLs (LoadLibrary) or call any other function that MIGHT cause a DLL to be loaded, which pretty much rules out anything beyond simple initialization and functions exported by Kernel32.
See the last few paragraphs of the DllMain (MSDN) docs for details.
In this topic they said that zero initialization is not static initialization.
Can anyone explain why?
3.6.2/2 said:
Together, zero-initialization and constant initialization are called
static initialization;
It is definition of Static initialization, means that zero-initialization is static initialization and constant-initialization is static Initialization
This answer assumes that you know what static storage duration means.
In C++03 this is specified as (3.6.2):
Objects with static storage duration (3.7.1) shall be zero-initialized
(8.5) before any other initialization takes place. Zero-initialization
and initialization with a constant expression are collectively called
static initialization; all other initialization is dynamic
initialization.
In practice, a program has different memory segments where it stores variables with static storage duration:
One segment is usually called .bss, where all static storage variables that are initialized to zero are stored.
Another segment is usually called .data, where all static storage variables that are explicitly initialized to a value are stored.
And further, there is a segment called .rodata where all const variables are stored.
(The reason why these are two different segments is mainly program startup performance, you can read more about that here.)
Zero initialization applies to all variables stored in .bss and constant initialization applies to all variables stored in .data. (And perhaps constant initialization applies to .rodata as well, depending on whether your system is RAM-based or if it has true ROM).
Collectively, all of this is called static initialization, since it applies to objects with static storage duration.
You forgot to notify the word "Together", very important in this sentence.
Zero-initialization + constant initialization = static initialization. Is that clearer ?
It's just vocabulary. There are clearly three phases of
initialization (for variables with static lifetime): zero
initialization, initialization using constant expressions, and
dynamic initialization. I find it convenient when talking about
this to use the term static initialization for the second step
(because it does take place statically, without the execution of
any user written code), even if the standard uses a somewhat
different terminology. In the end, it comes down to the same
thing:
int a;
int b = 42;
int c = someFunction();
Formally, all three variables will be zero-initialized. Then
b will be initialized with the constant expression 42; in
all likelyhood, it will never actually be zero-initialized,
because there's no way your code can ever see it before the
constant initialization. Finally, c will be initialized by
calling someFunction().
This order is true regardless of the order of the definitions,
and is guaranteed by the standard.
The post you link to says that zero-initialization is not static initialization. This is correct.
That is very different from zero-initialization is not a static initialization! This is not correct.
I heard that after some version of gcc using simply something like:
static A* a = new A();
return a;
Is thread-safe for a singleton and one wouldn't need something adapted from say http://locklessinc.com/articles/singleton_pattern/ anymore...
Does anyone have a specific reference or link to where I can read about this?
Section 6.7 of draft standard (n3337.pdf), point 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.88 If control re-enters the declaration recursively while the variable is being
initialized, the behavior is undefined.
GCC follows the cross-vendor Itanium C++ ABI. The relevant sections covering thread-safe initialization of function-local statics are 2.8 Initialization guard variables and 3.3.2 One-time Construction API, which says:
An implementation that does not anticipate supporting multi-threading may simply check the first byte (i.e., the byte with lowest address) of that guard variable, initializing if and only if its value is zero, and then setting it to a non-zero value.
However, an implementation intending to support automatically thread-safe, one-time initialization (as opposed to requiring explicit user control for thread safety) may make use of the following API functions:
...
There were some bugs in the early GCC implementation of that API, I think they are all fixed and it works correctly from GCC version 4.3 (possibly earlier, I don't recall and can't find a reference right now.)
However, Singleton is a bad, bad pattern, do not use it!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is static init thread-safe with VC2010?
I know that gcc and llvm-clang emit code to initialise local static variables in a threadsafe manner (which allows one to escape the static order initialisation fiasco by wrapping global statics in functions).
This msdn blog post, however, is the best documentation I can find of vcc's behaviour in these circumstances, and purports that static initialisation cannot ever be threadsafe, because the initialiser for a local static could recursively call into the same scope.
I don't buy this argument - it is clearly a programming error if the initialiser relies on its own result.
So, given that this article is from 2004, that gcc and clang can do it, and that the current msvc documentation is ambiguous (stating that 'assigning' to a local static isn't threadsafe, but nothing more):
Is the initialisation of local statics now threadsafe in MSVC?
If not, why not, since it is clearly possible for gcc to do this, but very difficult for the programmer to add in afterwards.
The C++0x Standard says:
§6.7 Declaration statement [stmt.dcl]
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.88
If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
[ Example:
int foo(int i) {
static int s = foo(2*i); // recursive call - undefined
return i+1;
}
—end example ]
88) The implementation must not introduce any deadlock around execution of the initializer.
As expected, it is quite complete.
However the fact is that even older versions of gcc already complied with this, and in fact do even better: in case of recursive initialization, an exception is thrown.
Finally, regarding a programmer adding it afterward: you can normally do it if you have something like Compare And Swap available, and use a sufficiently small variable, relying on zero-initialization of the variable to mark its non-computed state. However I do agree it's much easier if it's baked in.
I am afraid I stopped followed VC++ progresses though, so I don't know where it stands now. My only advice would be... look it up at assembly level.
I heard it is already implemented in vs2010, but can not find any reference. Anyway in c++0x standard such initializations are explicitly required to be thread-safe, so sooner or later ms would comply I guess.
I have a single instance of a simple POD
a.hpp
class A {
struct Zzz {
A* m_aPtr;
int m_val;
}
static Zzz s_zzz;
};
a.cpp
A::Zzz A::s_zzz;
I expect that both s_zzz.m_aPtr and s_zzz.m_val will be initialized to zeros before any other static initialization in any other compilation unit and it is guaranteed by the language itself. Am I right about it?
Usually I provide default constructors for the structs. Say
A::Zzz::Zzz() :
m_aPtr(0),
m_val(0)
{
}
Will it create initialization order problem or introduce compiler dependencies?
At least in C++0x, you can rely on all zero-initialization being performed before any other initialization code runs.
From the C++0x FCD, section [basic.start.init]
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.
If you're considering using this variable from other initialization code, then an explicit constructor would be a big mistake, as it would run sometime mixed in with other initialization code, and overwrite whatever changes have already been made by other initializers.
I expect that both s_zzz.m_aPtr and
s_zzz.m_val will be initialized to
zeros before any other static
initialization in any other
compilation unit and it is guaranteed
by the language itself.
It will be zero-initialized, since it's a static lifetime variable at namespace scope.
That zero-initialization happens before any dynamic initialization (an example of dynamic initializatin is when you some explicit initialization, or the class has a constructor).
The order of zero-initialization between different translation units is not defined, but there's not any way to detect it or rely on it since it happens before anything else, so it doesn't matter.
Re your point 2, it's rather unclear what you're asking about.
But for your static lifetime object, the effect is just that it's first zero-initialized, and then during dynamic initialization your constructor is used to zero it again (although the compiler might be smart enough to optimize away that redundant extra initialization).
Cheers & hth.,
ERRATA: Ben Voigt has provided a convincing example that the last paragraph above is wrong. So please disregard. The presence of the constructor means that the object can be dynamically initialized at some point before, between or after operations that change it, causing rather unpredictable results…
There are no guarantees about initialization order of statics between compilation units (see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14).
If it has a constructor, it will no longer be a POD, unfortunately.
Static data is always initialised to zero.
No it shouldn't introduce any initialisation problems.
When the application is loaded into memory, the static area is initialised to zero. This is before any code starts to execute.