Any risk of sharing local static variable of a method between instances? - c++

Let's say I create:
class Hello {
public:
int World(int in)
{
static int var = 0; // <<<< This thing here.
if (in >= 0) {
var = in;
} else {
cout << var << endl;
}
}
};
Now, if I do:
Hello A;
Hello B;
A.World(10);
A.World(-1);
B.World(-1);
I'm getting output of "10" followed by another "10". The value of the local variable of a method just crossed over from one instance of a class to another.
It's not surprising - technically methods are just functions with a hidden this parameter, so a static local variable should behave just like in common functions. But is it guaranteed? Is it a behavior enforced by standard, or is it merely a happy byproduct of how the compiler handles methods? In other words - is this behavior safe to use? (...beyond the standard risk of baffling someone unaccustomed...)

Yes. It doesn't matter if the function is a [non-static] member of a class or not, it's guranteed to have only one instance of it's static variables.
Proper technical explanation for such variables is that those are objects with static duration and internal linkage - and thus those names live until program exits, and all instances of this name refer to the same entity.

Just one thing to add to the correct answer. If your class was templated, then the instance of var would only be shared amongst objects of the same instantiation type. So if you had:
template<typename C>
class Hello {
public:
int World(int in)
{
static int var = 0; // <<<< This thing here.
if (in >= 0) {
var = in;
} else {
cout << var << endl;
}
}
};
And then:
Hello<int> A;
Hello<int> B;
Hello<unsigned> C;
A.World(10);
A.World(-1);
B.World(-1);
C.World(-1);
Then the final output would be "0" rather than "10", because the Hello<unsigned> instantiation would have its own copy of var.

If we are talking about the Windows Compiler it's guaranteed
https://msdn.microsoft.com/en-us/library/y5f6w579.aspx
The following example shows a local variable declared static in a member function. The static variable is available to the whole program; all instances of the type share the same copy of the static variable.
They use an example very similar to yours.
I don't know about GCC

Yes, it is guaranteed. Now, to answer the question "Any risk of sharing local static variable of a method between instances?" it might be a bit less straightforward. There might be potential risks in the initialization and utilization of the variable and these risks are specific to variables local to the method (as opposed to class variables).
For the initialization, a relevant part in the standard is 6.7/4 [stmt.dcl]:
Dynamic initialization of a block-scope variable with static storage
duration (3.7.1) or thread storage duration (3.7.2) is performed 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.
In the simple cases, everything should work as expected. When the construction and initialization of the variable is more complex, there will be risks specific to this case. For instance, if the constructor throws, it will have the opportunity to throw again on the next call. Another example would be recursive initialization which is undefined behavior.
Another possible risk is the performance of the method. The compiler will need to implement a mechanism to ensure compliant initialization of the variable. This is implementation-dependent and it could very well be a lock to check if the variable is initialized, and that lock could be executed every time the method is called. When that happens, it can have a significant adverse effect on performance.

Related

static object intialization and compilation c++ [duplicate]

If a variable is declared as static in a function's scope it is only initialized once and retains its value between function calls. What exactly is its lifetime? When do its constructor and destructor get called?
void foo()
{
static string plonk = "When will I die?";
}
The lifetime of function static variables begins the first time[0] the program flow encounters the declaration and it ends at program termination. This means that the run-time must perform some book keeping in order to destruct it only if it was actually constructed.
Additionally, since the standard says that the destructors of static objects must run in the reverse order of the completion of their construction[1], and the order of construction may depend on the specific program run, the order of construction must be taken into account.
Example
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Output:
C:>sample.exe
Created in foo
Destroyed in foo
C:>sample.exe 1
Created in if
Created in foo
Destroyed in foo
Destroyed in if
C:>sample.exe 1 2
Created in foo
Created in if
Destroyed in if
Destroyed in foo
[0] Since C++98[2] has no reference to multiple threads how this will be behave in a multi-threaded environment is unspecified, and can be problematic as Roddy mentions.
[1] C++98 section 3.6.3.1 [basic.start.term]
[2] In C++11 statics are initialized in a thread safe way, this is also known as Magic Statics.
Motti is right about the order, but there are some other things to consider:
Compilers typically use a hidden flag variable to indicate if the local statics have already been initialized, and this flag is checked on every entry to the function. Obviously this is a small performance hit, but what's more of a concern is that this flag is not guaranteed to be thread-safe.
If you have a local static as above, and foo is called from multiple threads, you may have race conditions causing plonk to be initialized incorrectly or even multiple times. Also, in this case plonk may get destructed by a different thread than the one which constructed it.
Despite what the standard says, I'd be very wary of the actual order of local static destruction, because it's possible that you may unwittingly rely on a static being still valid after it's been destructed, and this is really difficult to track down.
The existing explanations aren't really complete without the actual rule from the Standard, found in 6.7:
The zero-initialization of all block-scope variables with static storage duration or thread storage duration is performed before any other initialization takes place. Constant initialization 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. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
FWIW, Codegear C++Builder doesn't destruct in the expected order according to the standard.
C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
... which is another reason not to rely on the destruction order!
The Static variables are come into play once the program execution starts and it remain available till the program execution ends.
The Static variables are created in the Data Segment of the Memory.

Lifetime of local static variables in C++11 [duplicate]

If a variable is declared as static in a function's scope it is only initialized once and retains its value between function calls. What exactly is its lifetime? When do its constructor and destructor get called?
void foo()
{
static string plonk = "When will I die?";
}
The lifetime of function static variables begins the first time[0] the program flow encounters the declaration and it ends at program termination. This means that the run-time must perform some book keeping in order to destruct it only if it was actually constructed.
Additionally, since the standard says that the destructors of static objects must run in the reverse order of the completion of their construction[1], and the order of construction may depend on the specific program run, the order of construction must be taken into account.
Example
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Output:
C:>sample.exe
Created in foo
Destroyed in foo
C:>sample.exe 1
Created in if
Created in foo
Destroyed in foo
Destroyed in if
C:>sample.exe 1 2
Created in foo
Created in if
Destroyed in if
Destroyed in foo
[0] Since C++98[2] has no reference to multiple threads how this will be behave in a multi-threaded environment is unspecified, and can be problematic as Roddy mentions.
[1] C++98 section 3.6.3.1 [basic.start.term]
[2] In C++11 statics are initialized in a thread safe way, this is also known as Magic Statics.
Motti is right about the order, but there are some other things to consider:
Compilers typically use a hidden flag variable to indicate if the local statics have already been initialized, and this flag is checked on every entry to the function. Obviously this is a small performance hit, but what's more of a concern is that this flag is not guaranteed to be thread-safe.
If you have a local static as above, and foo is called from multiple threads, you may have race conditions causing plonk to be initialized incorrectly or even multiple times. Also, in this case plonk may get destructed by a different thread than the one which constructed it.
Despite what the standard says, I'd be very wary of the actual order of local static destruction, because it's possible that you may unwittingly rely on a static being still valid after it's been destructed, and this is really difficult to track down.
The existing explanations aren't really complete without the actual rule from the Standard, found in 6.7:
The zero-initialization of all block-scope variables with static storage duration or thread storage duration is performed before any other initialization takes place. Constant initialization 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. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
FWIW, Codegear C++Builder doesn't destruct in the expected order according to the standard.
C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
... which is another reason not to rely on the destruction order!
The Static variables are come into play once the program execution starts and it remain available till the program execution ends.
The Static variables are created in the Data Segment of the Memory.

Crazy talk (paranoid about initialization)

I learned long ago that the only reliable way for a static member of be initialized for sure is to do in a function. Now, what I'm about to do is to start returning static data by non-const reference and I need someone to stop me.
function int& dataSlot()
{
static int dataMember = 0;
return dataMember;
}
To my knowledge this is the only way to ensure that the static member is initlized to zero. However, it creates obscure code like this:
dataSlot() = 7; // perfectly normal?
The other way is to put the definition in a translation unit and keep the stuff out of the header file. I have nothing against that per se but I have no idea what the standard says regard when and under what circumstances that is safe.
The absolute last thing I wanna end up doing is accidently accessing uninitialized data and losing control of my program.
(With the usual cautions against indiscriminate use of globals...) Just declare the variable at global scope. It is guaranteed to be zero-initialized before any code runs.
You have to be more cunning when it comes to types with non-trivial constructors, but ints will work fine as globals.
Returning a non-const reference in itself is fairly harmless, for example it's what vector::at() does, or vector::iterator::operator*.
If you don't like the syntax dataSlot() = 7;, you could define:
void setglobal(int i) {
dataSlot() = i;
}
int getglobal() {
return dataSlot();
}
Or you could define:
int *dataSlot() {
static int dataMember = 0;
return &dataMember;
}
*dataSlot() = 7; // better than dataSlot() = 7?
std::cout << *dataSlot(); // worse than std::cout << dataSlot()?
If you want someone to stop you, they need more information in order to propose an alternative to your use of mutable global state!
It is called Meyers singletor, and it is almost perfectly safe.
You have to take care that the object is created when the function dataSlot() is called, but it is going to be destroyed when the program exists (somewhere when global variables are destructed), therefore you have to take special care. Using this function in destructors is specially dangerous and might cause random crashes.
I learned long ago that the only reliable way for a static member of be initialized for sure is to do in a function.
No, it isn't. The standard guarantees that:
All objects with static storage (both block and file or class-static scope) with trivial constructors are initialized before any code runs. Any code of the program at all.
All objects with file/global/class-static scope and non-trivial constructos are than initialized before the main function is called. It is guaranteed that if objects A and B are defined in the same translation unit and A is defined before B, than A is initialized before B. However order of construction of objects defined in different translation units is unspecified and will often differ between compilations.
Any block-static objects are initialized when their declaration is reached for the first time. Since C++03 standard does not have any support for threads, this is NOT thread-safe!
All objects with static storage (both block and file/global/class-static scoped) are destroyed in the reverse order of their constructors completing after the main() function exits or the application terminates using exit() system call.
Neither of the methods is usable and reliable in all cases!
Now, what I'm about to do is to start returning static data by non-const reference and I need someone to stop me.
Nobody is going to stop you. It's legal and perfectly reasonable thing to do. But make sure you don't fall in the threads trap.
E.g. any reasonable unit-test library for C++ automatically registers all test cases. It does it by having something like:
std::vector<TestCase *> &testCaseList() {
static std::vector<TestCase *> test_cases;
return test_cases;
}
TestCase::TestCase() {
...
testCaseList().push_back(this);
}
Because that's the one of only two ways to do it. The other is:
TestCase *firstTest = NULL;
class TestCase {
...
TestCase *nextTest;
}
TestCase::TestCase() {
...
nextTest = firstTest;
firstTest = this;
}
this time using the fact that firstTest has trivial constructor and therefore will be initialized before any of the TestCases that have non-trivial one.
dataSlot() = 7; // perfectly normal?
Yes. But if you really want, you can do either:
The old C thing of
#define dataSlot _dataSlot()
in a way the errno "variable" is usually defined,
Or you can wrap it in a struct like
class dataSlot {
Type &getSlot() {
static Type slot;
return slot;
}
operator const Type &() { return getSlot(); }
operator=(Type &newValue) { getSlot() = newValue; }
};
(the disadvantage here is that compiler won't look for Type's method if you try to invoke them on dataSlot directly; that's why it needs the operator=)
You could make yourself 2 functions, dataslot() and set_dataslot() which are wrappers round the actual dataslot, a bit like this:
int &_dataslot() { static int val = 0; return val; }
int dataslot() { return _dataslot(); }
void set_dataslot(int n) { _dataslot() = n; }
You probably wouldn't want to inline that lot in a header, but I've found some C++ implementations do rather badly if you try that sort of thing anyway.

c++: initializing static string members

I'm having some problems initializing static string members in c++. I have several classes and each one is holding several static string members that represent an id. When I am initializing the variables by calling a static function everything is fine. However, when I'd like to assign one variable with the value of another it still holds empty string. What's problem with this code?
std::string A::id()
{
std::stringstream sst;
sst << "id" << i;
i++;
return sst.str();
}
std::string B::str = A::id(); //prints "id0";
std::string C::str = "str"; //prints str
std::string D::str = B::str; //prints "" <-- what's wrong here?
std::string D::str2 = C::str; //prints ""
It appears as if the variables I am referring to (B::str and C::str) havent been initialized yet. But I assume when D::str = B::str is executed C::str is initialized at the latest and therefore D::str should also hold the string "id0".
This is Static Initialization Fiasco.
As per the C++ Standard the initialization order of objects with static storage duration is unspecified if they are declared in different Translation units.
Hence any code that relies on the order of initialization of such objects is bound to fail, and this problem is famously known as The Static Initialization Fiasco in C++.
Your code relies on the condition that Initialization of B::str and C::str happens before D::str, which is not guaranteed by the Standard. Since these 3 static storage duration objects reside in different translation units they might be initialized in Any order.
How to avoid it?
The solution is to use Construct On First Use Idiom,in short it means replacing the global object, with a global function, that returns the object by reference. The object returned by reference should be local static, Since static local objects are constructed the first time control flows over their declaration, the object will be created only on the first call and on every subsequent call the same object will be returned, thus simulating the behavior you need.
This should be an Interesting read:
How do I prevent the "static initialization order fiasco"?
There is no guaranteed order of initialization for static variables. So don't rely on it.
Instead init them with actual literal's, or better yet, init them at run-time when they are really needed.

What is the lifetime of a static variable in a C++ function?

If a variable is declared as static in a function's scope it is only initialized once and retains its value between function calls. What exactly is its lifetime? When do its constructor and destructor get called?
void foo()
{
static string plonk = "When will I die?";
}
The lifetime of function static variables begins the first time[0] the program flow encounters the declaration and it ends at program termination. This means that the run-time must perform some book keeping in order to destruct it only if it was actually constructed.
Additionally, since the standard says that the destructors of static objects must run in the reverse order of the completion of their construction[1], and the order of construction may depend on the specific program run, the order of construction must be taken into account.
Example
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Output:
C:>sample.exe
Created in foo
Destroyed in foo
C:>sample.exe 1
Created in if
Created in foo
Destroyed in foo
Destroyed in if
C:>sample.exe 1 2
Created in foo
Created in if
Destroyed in if
Destroyed in foo
[0] Since C++98[2] has no reference to multiple threads how this will be behave in a multi-threaded environment is unspecified, and can be problematic as Roddy mentions.
[1] C++98 section 3.6.3.1 [basic.start.term]
[2] In C++11 statics are initialized in a thread safe way, this is also known as Magic Statics.
Motti is right about the order, but there are some other things to consider:
Compilers typically use a hidden flag variable to indicate if the local statics have already been initialized, and this flag is checked on every entry to the function. Obviously this is a small performance hit, but what's more of a concern is that this flag is not guaranteed to be thread-safe.
If you have a local static as above, and foo is called from multiple threads, you may have race conditions causing plonk to be initialized incorrectly or even multiple times. Also, in this case plonk may get destructed by a different thread than the one which constructed it.
Despite what the standard says, I'd be very wary of the actual order of local static destruction, because it's possible that you may unwittingly rely on a static being still valid after it's been destructed, and this is really difficult to track down.
The existing explanations aren't really complete without the actual rule from the Standard, found in 6.7:
The zero-initialization of all block-scope variables with static storage duration or thread storage duration is performed before any other initialization takes place. Constant initialization 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. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.
FWIW, Codegear C++Builder doesn't destruct in the expected order according to the standard.
C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
... which is another reason not to rely on the destruction order!
The Static variables are come into play once the program execution starts and it remain available till the program execution ends.
The Static variables are created in the Data Segment of the Memory.