I have a C++ program with three source files:
// main.cpp
auto return_value = managed_call(int value);
// managed.cpp
#include "private_impl.hpp"
int managed_call(int arg) {
if (arg == 0)
return private_func();
else
return arg;
}
//private_impl.cpp
static some_type some_var = construct_static_object_might_blow();
int private_func() {
....
return 42;
}
My question is about the initialization of the static object in private_impl.cpp: "when does that take place?" or more specifically - is it only initialized if the private_func function is called?
Update
I actually simplified the example a bit too much; the code in question will be run as a Python extension - i.e. it is dlopen()which is the crucial init step. This SO question turned out to be spot on.
When is the static init called in C++
I suppose that you mean, when is the variable with static storage duration initialised. If the variable has static initialisation, that happens before anything else.
If the variable has dynamic initialisation, then it is initially zero initialised during the static initialisation. The exact point of dynamic initialisation is implementation defined. The variable will be initialised at some point before it - or any other variable from that translation unit (TU) - is accessed the first time, or before any function from that TU is called.
is it only initialized if the private_func function is called?
It may be initialised whether private_func is called or not. But if private_func is called, then the variable will be initialised at some point before the function call. It is unclear to me whether the initialisation can be deferred so far that it never happens.
Relevant standard quotes in this SO post.
You have no guarantee about the order that static global objects are initialized in across compilation units. See https://isocpp.org/wiki/faq/ctors#static-init-order - you do have guarantees within a translation unit though.
The best way to not get bitten by this is to not have globals (singletons) in the first place.
Non-local static variables are initialized when their compilation unit is initialized. The standard demands that a compilation unit is initialized no later than when an element from it is accessed first, so in your example construct_static_object_might_blow() will definitely be called before the first call of private_func(). The compiler may initialize private_impl.cpp's translation unit before calling main(), but this is nothing you should rely on.
A way to get by the static init, is by making a late init of the object.
Something like this
class some_class
{
public:
some_class() {} // do nothing
~some_class() {} // do nothing either
void set(some_type value) { val = value; }
some_type get() { return val; }
void shutDown { // do some cleanup }
private:
some_type val;
}
static some_class g_SomeClass ;
int main()
{
g_SomeClass.set("something");
g_SomeClass.shutDown();
return 0;
}
If your class need a proper way to shutdown, then you must do that by calling the shutdown.
Could that be a solution ?
Related
I'm trying to implement a factory pattern like this.
The problem right now is that the program terminates with a segfault in the register function because the map is not initialized yet.
// initialise the registered names map
std::map<std::string, factoryMethod> SourceFactory::registeredClasses_ = { };
bool SourceFactory::Register(std::string name, factoryMethod createMethod) {
// registeredClasses_ = { }; // This prevents the segfault but does not work for obvious reasons
auto temp = std::make_pair(name.c_str(), createMethod);
std::pair<std::map<std::string, factoryMethod>::iterator, bool> registeredPair =
SourceFactory::registeredClasses_.insert(temp);
return registeredPair.second;
}
Why is it possible for Register() to be called before the initialization of the map? I tried initializing the map in the header file but then I get the linker error
multiple definition of SourceFactory::registeredClasses_
A solution would be to set a static bool isInitialized=false and then initialize the map accordingly. But I hope this can be avoided.
It's possible when Register is called from a different translation unit before the registry has been initialised.
Unfortunately, adding a static flag would not solve anything because that would not be initialised either.
A convenient solution is to add a level of indirection:
// static
std::map<std::string, factoryMethod>& SourceFactory::registry()
{
static std::map<std::string, factoryMethod> registeredClasses;
return registeredClasses;
}
bool SourceFactory::Register(const std::string& name, factoryMethod createMethod) {
auto temp = std::make_pair(name, createMethod);
return registry().insert(temp).second;
}
This is a common problem known as the static initialisation order fiasco.
Objects with static storage duration at namespace scope are constructed in-order within a translation unit, but you don't know whether those in other translation units may undergo initialisation first.
Instead of having your container at namespace scope, make it function static (perhaps returned from a new GetRegistry() function?) so that it is constructed on first use. That could be use from main, use from initialisation of another static-duration "thing" (which is presumably where your Register call is coming from), use from the moon…
This is also why the proper way to write a singleton is to have a GetInstance() function that declares (staticly!) the instance within the function's scope.
A solution would be to set a static bool isInitialized=false and then initialize the map accordingly. But I hope this can be avoided.
Nope. Not only would you then have the same problem with the isInitialized flag, but there's nothing you can "do" with that information. You can't "initialize" something other than in an initializer, and the whole problem is that the initializer hasn't been used yet. You could assign to the map, but that would have undefined behaviour because you'd be assigning to something that doesn't exist yet… and then it would be initialized later anyway!
i have the following:
class base
{
public
void f();
...
}
void base::f()
{
static bool indicator=false;
.....
if(!indicator)
{
...
indicator=true;
}
}
class D:public base
{
...
}
in my main() i have:
main()
{
// first instance of D
base *d1 = new D();
d1->f();
....
// 2nd instance of D
base *d2 = new D();
d2->f();
}
i find that the first time i instantiate D and call d1->f() the static variable is set to false. but the 2nd time i call d2->f() the code does not even hit the line "static bool indicator=false;" and it is kept at true (from the first pass of d1-f()) This is exactly the behavior i want but i do not understand why this is happening. can someone please explain what is happening. thanks in advance
Static variables declared in member functions will keep their value between function calls. There will be only one copy over all instances, and all accesses to indicator from different instances will affect the same indicator. This means indicator will only be initialized once.
See here for more info: Static variables in member functions
Also this code does not toggle indicator, it always sets it to true if it's false (which I'm sure is the behaviour you want).
if(!indicator)
{
...
indicator=true;
}
This is precisely the behavior of static variables declared inside function blocks. It has been like that since the introduction of the feature in the C programming language.
The static declaration can also be applied to internal variables. Internal static variables are local to a particular function just as automatic variables are, but unlike automatics, they remain in existence rather than coming and going each time the function is activated. (K&R, page 61).
The static initializer is executed before the first invocation of the containing function. Being static, the variable retains its last state across the invocations.
These are two questions about static locals that have always bothered me and I haven't found a definitive answer to:
Question 1:
struct Test
{
static inline const char* name()
{
static const char* nameValue = "Name of Test";
return nameValue;
}
};
Since the method is inline, there should be a copy of this method in each compilation unit that calls it. But, there must be only one instance of the local static variable nameValue (correct me if I am wrong). How is this achieved? We have many instances of a function generated, but all of them refer to the same static local. Does the compiler maintain a global table of static locals associated with each function by name?
Question 2:
struct Init
{
Init() {printf("init created\n");}
~Init() {printf("init destroyed\n");}
};
struct Test
{
static void func()
{
static Init init;
}
};
The static local Init object is constructed only once, on the first call of func(). How does the compiler know when is the first call to func()? Does it maintain a flag at runtime, whether this is the first call of this func?
These are really two unrelated questions.
For the first, there are various solutions. Perhaps the most frequent
are something called weak symbols. Roughly speaking, the compiler
generates an instance under a specific name in every object file that
uses the function, and the linker throws out the duplicates, and only
keeps one in the final program.
For the second, the usual solution is to generate a boolean variable
associated with the object, and tests this when the object comes into
scope.
What is the rationale for not having static constructor in C++?
If it were allowed, we would be initializing all the static members in it, at one place in a very organized way, as:
//illegal C++
class sample
{
public:
static int some_integer;
static std::vector<std::string> strings;
//illegal constructor!
static sample()
{
some_integer = 100;
strings.push_back("stack");
strings.push_back("overflow");
}
};
In the absense of static constructor, it's very difficult to have static vector, and populate it with values, as shown above. static constructor elegantly solves this problem. We could initialize static members in a very organized way.
So why doesn't' C++ have static constructor? After all, other languages (for example, C#) has static constructor!
Using the static initialization order problem as an excuse to not introducing this feature to the language is and always has been a matter of status quo - it wasn't introduced because it wasn't introduced and people keep thinking that initialization order was a reason not to introduce it, even if the order problem has a simple and very straightforward solution.
Initialization order, if people would have really wanted to tackle the problem, they would have had a very simple and straightforward solution:
//called before main()
int static_main() {
ClassFoo();
ClassBar();
}
with appropriate declarations:
class ClassFoo {
static int y;
ClassFoo() {
y = 1;
}
}
class ClassBar {
static int x;
ClassBar() {
x = ClassFoo::y+1;
}
}
So the answer is, there is no reason it isn't there, at least not a technical one.
This doesn't really make sense for c++ - classes are not first class objects (like in e.g. java).
A (static|anything) constructor implies something is constructed - and c++ classes aren't constructed, they just are.
You can easily achieve the same effect though:
//.h
struct Foo {
static std::vector<std::string> strings;
};
//.cpp
std::vector<std::string> Foo::strings(createStrings());
IMO there's just no need for one more syntactic way of doing this.
In which translation unit would the static objects be placed?
Once you account for the fact that statics have to be placed in one (and only one) TU, it's then not "very difficult" to go the rest of the way, and assign values to them in a function:
// .h
class sample
{
public:
static int some_integer;
static std::vector<std::string> strings;
};
//.cpp
// we'd need this anyway
int sample::some_integer;
std::vector<std::string> sample::strings;
// add this for complex setup
struct sample_init {
sample_init() {
sample::some_integer = 100;
sample::strings.push_back("stack");
sample::strings.push_back("overflow");
}
} x;
If you really want the code for sample_init to appear in the definition of class sample, then you could even put it there as a nested class. You just have to define the instance of it in the same place you define the statics (and after they've been initialized via their default constructors, otherwise of course you can't push_back anything).
C# was invented 15-20 years after C++ and has a completely different build model. It's not all that surprising that it offers different features, and that some things are less simple in C++ than in C#.
C++0x adds a features to make it easier to initialize vectors with some data, called "initializer lists"
You could get by with putting your "static" members in their own class with their own constructor that performs their initialization:
class StaticData
{
int some_integer;
std::vector<std::string> strings;
public:
StaticData()
{
some_integer = 100;
strings.push_back("stack");
strings.push_back("overflow");
}
}
class sample
{
static StaticData data;
public:
sample()
{
}
};
Your static data member is guaranteed to be initialized before you first try to access it. (Probably before main but not necessarily)
Static implies a function that is disassociated with an object. Since only objects are constructed, it is not apparent why a static constructor would have any benefit.
You can always hold an object in a static scope which has been constructed in a static block, but the constructor you would use would still be declared as non-static. There's no rule that indicates you can't call a non-static method from a static scope.
Finally, C++ / C defines the start of a program to be when the main function is entered. Static blocks are called prior to the entry of the main function as part of setting up the "environment" of the evaluated code. If your environment dictates full control over the set-up and tear-down, then it's easy to argue that it's not really some environmental fixture as much as an inherit procedural component of the program. I know that the last bit is sort of code-philosophy (and that it's rationale could be interpreted differently), but one shouldn't put critical code "before" the official start of an executable's handing off "full control" to the code written by the programmer.
If I have two static variables in different compilation units, then their initialization order is not defined. This lesson is well learned.
The question I have: are all the static variables already allocated, when the first one is being initialized. In other words:
static A global_a; // in compilation unit 1
static B global_b; // in compilation unit 2
struct A {
A() { b_ptr = &global_b; }
B *b_ptr;
void f() { b_ptr->do_something(); }
}
int main() {
global_a.f();
}
Will b_ptr point to a valid piece of memory, where B is allocated and initialized at the time of the execution of the main function? On all the platforms?
Longer story:
The compilation unit 1 is Qt library.
The other one is my application. I have couple QObject derived classes, that I need to be able to instantiate by the class name string. For this I came up with a templated factory class:
class AbstractFactory {
public:
virtual QObject *create() = 0;
static QMap<const QMetaObject *, AbstractFactory *> m_Map;
}
QMap<const QMetaObject *, AbstractFactory *> AbstractFactory::m_Map; //in .cpp
template <class T>
class ConcreteFactory: public AbstractFactory {
public:
ConcreteFactory() { AbstractFactory::m_Map[&T::staticMetaObject] = this; }
QObject *create() { return new T(); }
}
#define FACTORY(TYPE) static ConcreteFactory < TYPE > m_Factory;
Then I add this macro on every QObject subclass definition:
class Subclass : public QObject {
Q_OBJECT;
FACTORY(Subclass);
}
Finally I can instantiate a class by the type name:
QObject *create(const QString &type) {
foreach (const QMetaObect *meta, AbstractFactory::m_Map.keys() {
if (meta->className() == type) {
return AbstractFactory::m_Map[meta]->create();
}
}
return 0;
}
So the class gets a static QMetaObject instance: Subclass::staticMetaObject from the Qt library - it is auto-generated in Q_OBJECT macro I think. And then the FACTORY macro creates a static ConcreteFactory< Subclass > instance. ConcreteFactory in its constructor tries to reference of Subclass::staticMetaObject.
And I was pretty happy with this implementation on linux (gcc), until I compiled it with Visual Studio 2008. For some reason AbstractFactory::m_Map was empty on the runtime, and the debugger would not break at the factory constructor.
So this is where the smell of static vars referencing other static vars is coming from.
How can I optimize this code to avoid all these traps?
Yes, the standard allows this.
There are a number of paragraphs in section [basic.life] which start out
Before the lifetime of an object has
started but after the storage which
the object will occupy has been
allocated or, after the lifetime of an
object has ended and before the
storage which the object occupied is
reused or released, any pointer that
refers to the storage location where
the object will be or was located may
be used but only in limited ways.
and there is a footnote which indicates that this specifically applies to your situation
For example, before the construction of a global object of non-POD class type
Short Answer: Its should work as you have coded it. See Ben Voigt Answer
Long Answer:
Do something like this:
Rather than let the compiler decide when globals are created, create them via static methods (with static function variables). This means that they will be deterministically created on first use (and destroyed in the reverse order of creation).
Even if one global uses another during its construction using this method gurantees that they will be created in the order required and thus be available for usage by the other (watch out for loops).
struct A
{
// Rather than an explicit global use
// a static method thus creation of the value is on first use
// and not at all if you don't want it.
static A& getGlobalA()
{
static A instance; // created on first use (destroyed on application exit)
// ^^^^^^ Note the use of static here.
return instance; // return a reference.
}
private:
A()
:b_ref(B::getGlobalB()) // Do the same for B
{} // If B has not been created it will be
// created by this call, thus guaranteeing
// it is available for use by this object
}
B& b_ref;
public:
void f() { b_ref.do_something(); }
};
int main() {
a::getGlobalA().f();
}
Though a word of warning.
Globals are an indication of bad design.
Globals that depend on other globals is another code smell (especially during construction/destruction).
Yes. All are located in .data section, that is allocated at once (and it's not heap).
Putting it another way: if you are able to take its address, then it's OK, because it surely won't change.
If B has a constructor, like A has, then the order that they are called is undefined. So your code won't work unless you are lucky. But if B doesn't require any code to initialise it, then your code will work. It's not implementation-defined.
Ah, but the idea that static variables are "not initialised" is quite wrong. They're always initialised, just not necessarily with your initialiser. In particular, all static variables are created with value zero before any other initialisation. For class objects, the members are zero. Therefore global_a.b_ptr above will always be a valid pointer, initially NULL and later &global_b. The effect of this is that use of non-pointers is unspecified, not undefined, in particular this code is well defined (in C):
// unit 1
int a = b + 1;
// unit 2
int b = a + 1;
main ... printf("%d\n", a + b); // 3 for sure
The zero initialisation guarantee is used with this pattern:
int get_x() {
static int init;
static int x;
if(init) return x;
else { x = some_calc(); init = 1; return x; }
}
which assures either a non-return due to infinite recursion, or, correctly initialised value.