Let's say I have a C library that has its own (de)initialization routine, as many of them do.
init_API();
deinit_API();
now let's say I want to provide another level of abstraction to the user, and abstract away these calls, using a class that's instantiated statically. The method I was thinking of:
struct API_initializer{
API_initializer(){
init_API();
if(API_init_failure)
throw (APIFailureException); //important
}
~API_initializer(){
deinit_API();
}
};
struct API_initializer_holder{
static API_initializer initializer;
};
Now, my question is, is this well-defined behavior? I.E., will the static constructor be called at some reasonable point, and will all the (static) variables the C API need be initialized properly? In addition, is it bad practice to throw an exception that the user has no way of catching?
In my experience it is a bad idea to try and rely on static initialization order.
A better idea would be to get rid of the holder, and just go:
int main()
{
API_initializer foo;
// rest of program
}
If you really want it to throw on failure then include a try..catch block.
NB. Make the class non-copyable to prevent accidents.
No, the program will break if the initialization is failed. You cannot catch the exception and handle it because the global variables(static member data) is initialized before main().
It's better to call init_API() and deinit_API() in main().
This is covered by §3.6.2 [basic.start.init]/p4-6 of the standard:
It is implementation-defined whether the dynamic initialization of a
non-local variable with static storage duration is done before the
first statement of main. If the initialization is deferred to some
point in time after the first statement of main, it shall occur before
the first odr-use of any function or variable defined in the same
translation unit as the variable to be initialized.35
[...]
If the initialization of a non-local variable with static or thread storage duration exits via an exception, std::terminate is called.
35 A non-local variable with static storage duration having initialization with side-effects must be initialized even if it is not odr-used.
As there's no way your static object can be in the same translation unit as a function in the C library you are wrapping, the only way to guarantee initialization would be to define it in the same translation unit as main(), which doesn't strike me as adding any kind of convenience to the end user.
In any event, it's probably not a good idea to cause std::terminate to be called by throwing an exception if initialization fails. The end user probably want to do better error handling than that.
The answer is: it depends. If the external API is implemented
in C (so that it will have no dynamic initialization), and it is
not used in any of your static initializers (which should be the
case, since there is no way that they can safely do init_API),
then the idiom is more or less safe (except that you shouldn't
allow an exception to escape from a static initializer. Whether
it is a good idea or not is another question; if the
initialization can fail, you may not want to execute it before
you can catch and handle the error, which means that you're in
main.
Related
I'm working on some C++ code and I've run into a question which has been nagging me for a while... Assuming I'm compiling with GCC on a Linux host for an ELF target, where are global static constructors and destructors called?
I've heard there's a function _init in crtbegin.o, and a function _fini in crtend.o. Are these called by crt0.o? Or does the dynamic linker actually detect their presence in the loaded binary and call them? If so, when does it actually call them?
I'm mainly interested to know so I can understand what's happening behind the scenes as my code is loaded, executed, and then unloaded at runtime.
Thanks in advance!
Update: I'm basically trying to figure out the general time at which the constructors are called. I don't want to make assumptions in my code based on this information, it's more or less to get a better understanding of what's happening at the lower levels when my program loads. I understand this is quite OS-specific, but I have tried to narrow it down a little in this question.
When talking about non-local static objects there are not many guarantees. As you already know (and it's also been mentioned here), it should not write code that depends on that. The static initialization order fiasco...
Static objects goes through a two-phase initialization: static initialization and dynamic initialization. The former happens first and performs zero-initialization or initialization by constant expressions. The latter happens after all static initialization is done. This is when constructors are called, for example.
In general, this initialization happens at some time before main(). However, as opposed to what many people think even that is not guaranteed by the C++ standard. What is in fact guaranteed is that the initialization is done before the use of any function or object defined in the same translation unit as the object being initialized. Notice that this is not OS specific. This is C++ rules. Here's a quote from the Standard:
It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of
namespace scope is done before the first statement of main. If the initialization is deferred to some point
in time after the first statement of main, it shall occur before the first use of any function or object defined
in the same translation unit as the object to be initialized
This depends heavy on the compiler and runtime. It's not a good idea to make any assumptions on the time global objects are constructed.
This is especially a problem if you have a static object which depends on another one being already constructed.
This is called "static initialization order fiasco". Even if thats not the case in your code, the C++Lite FAQ articles on that topic are worth a read.
This is not OS specific, rather its compiler specific.
You have given the answer, initialization is done in __init.
For the second part, in gcc you can guarantee the order of initialization with a __attribute__((init_priority(PRIORITY))) attached to a variable definition, where PRIORITY is some relative value, with lower numbers initialized first.
The grantees you have:
All static non-local objects in the global namespace are constructed before main()
All static non-local objects in another namespace are constructed before any functions/methods in that namespace are used (Thus allowing the compiler to potentially lazy evaluate them [but don't count on this behavior]).
All static non-local objects in a translation unit are constructed in the order of declaration.
Nothing is defined about the order between translation units.
All static non-local objects are destroyed in the reverse order of creation. (This includes the static function variables (which are lazily created on first use).
If you have globals that have dependencies on each other you have two options:
Put them in the same translation unit.
Transform them into static function variables retrieved and constructed on first use.
Example 1: Global A's constructor uses Global log
class AType
{ AType() { log.report("A Constructed");}};
LogType log;
AType A;
// Or
Class AType()
{ AType() { getLog().report("A Constructed");}};
LogType& getLog()
{
static LogType log;
return log;
}
// Define A anywhere;
Example Global B's destructor uses Global log
Here you have to grantee that the object log is not destroyed before the object B. This means that log must be fully constructed before B (as the reverse order of destruction rule will then apply). Again the same techniques can be used. Either put them in the same translation unit or use a function to get log.
class BType
{ ~BType() { log.report("B Destroyed");}};
LogType log;
BType B; // B constructed after log (so B will be destroyed first)
// Or
Class BType()
{ BType() { getLog();}
/*
* If log is used in the destructor then it must not be destroyed before B
* This means it must be constructed before B
* (reverse order destruction guarantees that it will then be destroyed after B)
*
* To achieve this just call the getLog() function in the constructor.
* This means that 'log' will be fully constructed before this object.
* This means it will be destroyed after and thus safe to use in the destructor.
*/
~BType() { getLog().report("B Destroyed");}
};
LogType& getLog()
{
static LogType log;
return log;
}
// Define B anywhere;
According to the C++ standard they are called before any function or object of their translation unit is used. Note that for objects in the global namespace this would mean they are initialized before main() is called. (See ltcmelo's and Martin's answers for mote details and a discussion of this.)
If I have some variables that I'm initializing statically (before main begins), am I free to use any built-in stuff in these constructors, like <iostream> or <vector>?
The "static initialization order fiasco" occurs because the order in which static variables are initialized (among different translation units) is undefined.
So what if something benign like
std::cout << "Hello" << std::endl;
happens to rely on some static variable inside <iostream> being initialized ahead of time? (I'm not saying it does, but assume it did.) What's to say that these static variables inside built-in libraries are initialized before my own static variables? Like inside say "Person.cpp" or whatever.
Edit: Is std::cout guaranteed to be initialized? was suggested as a duplicate to this question. However, I think my question is slightly broader in scope because it asks about any standard built-in library, rather than just <iostream>.
The C++ standards make no strong statements of the behavior of the program before the start of main, or after main has completed.
In experience, I have found a number of issues where the C++ runtime has destroyed some object (e.g. resources used for management of std::mutex), which have created a deadlock in the destruction of a complex type.
I would recommend the following pattern for static's
C++ creates objects declared static in a function in the order they are executed. This leaves a pattern which will ensure that objects exist as they are needed.
AnObject * AnObject::getInstance() {
static AnObject a;
return &a;
}
This should be executed to get hold of the global, and will occur at the point when getInstance() is called.
C++ 11 onwards
This code is guaranteed to be thread-safe, where if multiple threads of execution arrive in getInstance, only one will construct the object and the rest will wait.
Pre C++ 11
Creating this pattern replaces ill-defined order with thread safety issues.
Luckily, it will be possible to create a criticalsection/mutex primative in main, which is able to arbitrate.
In some OSs (e.g. InitializeCriticalSection and Windows), these locks can safely be created before main as static variables.
AnObject * AnObject::getInstance() {
EnterCriticalSection( &aObjectcrit );
static AnObject a;
LeaveCriticalSection( &aObjectcrit );
return &a;
}
Assuming you have initialized aObjectcrit either in or before this function is called.
The result of this pattern is a form of onion construction, where objects are required in the order they are needed, and when the program exits, they are destroyed in the reverse order they were created in.
You're confusing objects (std::cout) and types (std::vector). The former is covered by the linked question, and the latter is a type. Static initialization applies to objects, but not to types.
The title basically says it all, i wonder when static members of a c++ class are initialized and when they go out of scope.
I need this for the following problem. I have many objects of a class Foo and each object needs access to a resource, encapsulated by another class Bar. Synchronization is not an issue, so i want all objects to share the same Bar instance.
I'm using a simple managed pointer for reference counting.
Can i do the following:
class Foo {
private:
static managed_pointer<Bar> staticBar;
public:
Foo() {
if(!staticBar)
staticBar = new Bar;
}
/*
* use staticBar in various non-static member functions
*/
};
managed_pointer<Bar> Foo::staticBar = NULL;
the managed_pointer staticBar should delete the Bar object as soon as it goes out of scope - but when does this happen? when the last instance of Foo is destructed? on application exit?
Thanks for your advice!
statics and globals are initialized right before the program starts (before main is called, the program actually starts before that) and go out of scope after main exits.
Exceptions - local statics (static variables declared inside functions) and unused template class staticmembers.
It has nothing to do with the number of instances.
The standard does not specify a precise order of initialization, it is implementation specific. They will be instantiated at the start of the program and deallocated at the end.
You have to be very careful with what you are doing, because if you have some other static objects that rely on this object to exist, it's UB. There is no telling in what order they will be initialized.
You could possibly look into something like boost::call_once to ensure it's initialized once, but I wouldn't rely on the order the statics are initialized.
For all I know, you code would work, but I've been bitten by the static initialization issue before so I wanted to warn you.
EDIT: Also in your code, when the managed_ptr will go out of scope (end of program), it will delete the memory allocated automatically. But you should not do anything non-trivial in Bar's destructor as you may trigger UB by calling into other free'd instances or even code that has been removed (as it happened to me once where a dynamic library had been removed). Essentially you are in a minefield, so watch out.
The first thing that pops out of your question is the common misconception that scope and lifetime are equivalent concepts. They are not. In some cases as with local variables, the lifetime is bound to a particular context, but that is not always the case.
A class static member variable has class scope (it is accessible anywhere in the program) and static lifetime, which means that it will be initialized in order with respect to the other static variables in the same translation unit, and in an undefined order with respect to other static variables in other translation units, before main (caveat: initialization need not be performed before the first statement in main, but it is guaranteed to be before the first odr-use of the variable).
I have heard that using static member objects is not a very good practice.
Say for example, I have this code:
class Foo {
...
static MyString str;
};
I define and initialize this variable in the implementation file of this class as:
MyString Foo::str = "Some String"; // This is fine as my string API handles this.
When I run this code, I get a warning:
warning:'Foo::str' requires global construction.
I have quite much of such members in my class, what is the best way to handle this.
Thanks,
Most of the arguments against them are the same as for global variables:
Initialization order between different compilation units is undefined.
Initialization order inside one compilation unit may affect the behavior — thus non trivial ordering may be required.
If a constructor throws an exception you can't catch it, your program is terminated.
APPENDED: To handle this properly you must either make sure that above points don't apply to your code and ignore the warning, or redesign your program: Do you really need them static? Why not use const char* Foo::str = "Some String";?
The biggest reason for concern with this example is that constructing the static member object happens before main() and destruction happens after main() (or when you call exit()). So far, that's a good thing. But when you have multiple objects like this in your program, you risk a bug where code attempts to use an object that has not yet been constructed or has already been destroyed.
The C++ FAQ Lite has some helpful discussion on this topic, including a workaround/solution. Recommended reading is questions 10.14 through 10.18. 10.17 is most directly applicable to your example.
Using a static member, you are not guaranteeing thread safety, imagine two threads trying to access the static member - now what would be the value of that member - was it the one from thread x or thread y, this also induces another side-effect, race conditions, where one thread modifies the static member before the other thread completes... in other words, using a static member can be hazardous...
As an example, it is required to know the number of instances of a class. This would require a class static member to track the count of instances.
There is nothing wrong in having a static member of a class if the problem solution requires such a design. It's just that the nitty gritties have to be taken care as mentioned in other posts.
I'm working on some C++ code and I've run into a question which has been nagging me for a while... Assuming I'm compiling with GCC on a Linux host for an ELF target, where are global static constructors and destructors called?
I've heard there's a function _init in crtbegin.o, and a function _fini in crtend.o. Are these called by crt0.o? Or does the dynamic linker actually detect their presence in the loaded binary and call them? If so, when does it actually call them?
I'm mainly interested to know so I can understand what's happening behind the scenes as my code is loaded, executed, and then unloaded at runtime.
Thanks in advance!
Update: I'm basically trying to figure out the general time at which the constructors are called. I don't want to make assumptions in my code based on this information, it's more or less to get a better understanding of what's happening at the lower levels when my program loads. I understand this is quite OS-specific, but I have tried to narrow it down a little in this question.
When talking about non-local static objects there are not many guarantees. As you already know (and it's also been mentioned here), it should not write code that depends on that. The static initialization order fiasco...
Static objects goes through a two-phase initialization: static initialization and dynamic initialization. The former happens first and performs zero-initialization or initialization by constant expressions. The latter happens after all static initialization is done. This is when constructors are called, for example.
In general, this initialization happens at some time before main(). However, as opposed to what many people think even that is not guaranteed by the C++ standard. What is in fact guaranteed is that the initialization is done before the use of any function or object defined in the same translation unit as the object being initialized. Notice that this is not OS specific. This is C++ rules. Here's a quote from the Standard:
It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of
namespace scope is done before the first statement of main. If the initialization is deferred to some point
in time after the first statement of main, it shall occur before the first use of any function or object defined
in the same translation unit as the object to be initialized
This depends heavy on the compiler and runtime. It's not a good idea to make any assumptions on the time global objects are constructed.
This is especially a problem if you have a static object which depends on another one being already constructed.
This is called "static initialization order fiasco". Even if thats not the case in your code, the C++Lite FAQ articles on that topic are worth a read.
This is not OS specific, rather its compiler specific.
You have given the answer, initialization is done in __init.
For the second part, in gcc you can guarantee the order of initialization with a __attribute__((init_priority(PRIORITY))) attached to a variable definition, where PRIORITY is some relative value, with lower numbers initialized first.
The grantees you have:
All static non-local objects in the global namespace are constructed before main()
All static non-local objects in another namespace are constructed before any functions/methods in that namespace are used (Thus allowing the compiler to potentially lazy evaluate them [but don't count on this behavior]).
All static non-local objects in a translation unit are constructed in the order of declaration.
Nothing is defined about the order between translation units.
All static non-local objects are destroyed in the reverse order of creation. (This includes the static function variables (which are lazily created on first use).
If you have globals that have dependencies on each other you have two options:
Put them in the same translation unit.
Transform them into static function variables retrieved and constructed on first use.
Example 1: Global A's constructor uses Global log
class AType
{ AType() { log.report("A Constructed");}};
LogType log;
AType A;
// Or
Class AType()
{ AType() { getLog().report("A Constructed");}};
LogType& getLog()
{
static LogType log;
return log;
}
// Define A anywhere;
Example Global B's destructor uses Global log
Here you have to grantee that the object log is not destroyed before the object B. This means that log must be fully constructed before B (as the reverse order of destruction rule will then apply). Again the same techniques can be used. Either put them in the same translation unit or use a function to get log.
class BType
{ ~BType() { log.report("B Destroyed");}};
LogType log;
BType B; // B constructed after log (so B will be destroyed first)
// Or
Class BType()
{ BType() { getLog();}
/*
* If log is used in the destructor then it must not be destroyed before B
* This means it must be constructed before B
* (reverse order destruction guarantees that it will then be destroyed after B)
*
* To achieve this just call the getLog() function in the constructor.
* This means that 'log' will be fully constructed before this object.
* This means it will be destroyed after and thus safe to use in the destructor.
*/
~BType() { getLog().report("B Destroyed");}
};
LogType& getLog()
{
static LogType log;
return log;
}
// Define B anywhere;
According to the C++ standard they are called before any function or object of their translation unit is used. Note that for objects in the global namespace this would mean they are initialized before main() is called. (See ltcmelo's and Martin's answers for mote details and a discussion of this.)