I am looking at a case where I would have a global static std::vector that I would need to guarantee is initialized (constructed) before certain static objects in an assortment of translation units.
When I look up how to handle this I come across two proposed solutions:
Have a static object in a global function that is used in place of a global static object.
Schwarz Counters
My concern with using a Schwarz counter is that the std::vector will be initialized twice. From this link I get "A useful technique for ensuring that a global object is initialized only once and before its first use is to maintain a count of the number of translation units using it."
How does it work that the global is only initialized once? By my reasoning it would be initialized twice. Once in the normal course of static initialization and once when the first instance of the Schwarz counter is initialized.
On a related note, what would the initialization code look like in the Schwarz counter constructor? I can only think of using a placement new.
I can only say how I've implemented it in the past: I design
a special "no-op" constructor, which does nothing, and use
placement new in the Schwartz counter. Something like:
class ForUseAsStatic
{
public:
enum MakeCtorNoop { makeCtorNoop };
ForUseAsStatic(); // normal ctor, called by Schwartz counter.
ForUseAsStatic( MakeCtorNoop );
// no-op constructor, used when
// defining the variable.
};
Formally, this isn't guaranteed—the compiler is allowed to
set the memory to 0 again just before calling the constructor,
but I've never heard of a compiler which does.
It would also be possible to put some sort of flag in the class
itself, tested by the constructor. This would only be valid for
static objects, of course (since it needs zero initialization in
order to work).
Another possible technique (which I've seen used in some
libraries) is to declare the memory for the objects in
assembler, or as a byte array if the compiler has some means of
forcing alignment. Data names are not normally mangled, so this
will generally work, even if it is formally undefined behavior.
(For the standard library, of course, the library authors can
request extensions in the compiler to help them with the
problem.)
Finally: today, the singleton idiom, or something similar, is
generally preferred to such work-arounds. It does mean that you
have to write myobj().xxx, rather than just myobj.xxx, but
this is not generally felt to be an issue.
I don't think there is a right answer to the static initialisation problem the behaviour is undefined, and the selection of a solution depends on the specific circumstances. It depends on:
Your compiler and its implementation
most compilers offer guarantees within a single compilation unit
order can be determined by the linker and sometimes influenced with #pragma
initialisation can occur at any point before main begins executing.
Whether destructors will be called for global functions with static variables and when.
The application architecture
Whether a .DLL is used, certain environments have reduced support for managing static construction/destruction in DLLs particularly when demand loaded.
Whether the application is threaded, this can have an effect on how global functions with static variables get called.
Possibly the best advice is to try to avoid this fiasco by designing your system in another way, although this might not be practical. It does sound like your application does not need to take some of the concerns about portability into account and targets a specific environment with a specific compiler.
#pragma / Compiler options
One option you might not have considered is whether there is some compiler support for what you need.
For windows see:
http://support.microsoft.com/kb/104248
For g++:
Enable the init-priority and use __attribute__ ((init_priority (n))).
Getting Swartz counters to work
What some examples omit is the object that is space is just reserved for the object being allocated that is appropriately aligned. This avoids one of the constructions you mention. For example in g++ gnu use:
typedef char fake_istream[sizeof(istream)] __attribute__ ((aligned(__alignof__(istream))))
...
fake_istream cin;
to allocate the space for the object. All code outside that compilation unit will refer to this area as extern istream cin (via the headers) and is initialised with an in-place new. Some care should be taken to make sure that the nifty counter is thread-safe (atomic).
You could use another level of indirection: have your global variable be a pointer to the vector (which will be zero-initialized), and have your counter new the vector and store the result in the pointer.
Related
Not sure if this has already been asked before. While answering this very simple question, I asked myself the following instead. Consider this:
void foo()
{
int i{};
const ReallyAnyType[] data = { item1, item2, item3,
/* many items that may be potentially heavy to recreate, e.g. of class type */ };
/* function code here... */
}
Now in theory, local variables are recreated every time control reaches function, right? I.e. look at int i above - it's going to be recreated on the stack for sure. What about the array above? Can a compiler be as smart as to optimize its creation to occur only once, or do I need a static modifier here anyway? What about if the array is not const? (OK, if it's not const, there probably i snot sense in creating it only once, since re-initialization to the default state may be required between calls due to modifications being made during function execution.)
Might sound like a basic question, but for some reason I still ponder. Also, ignore the "why would you want to do this" - this is just a language question, not applied to a certain programming problem or design. I mean both C and C++ here. Should there be differences between the two regarding this question, please outline those.
There a two questions here, I think:
Can a compiler optimize a non-static const object to be effectively static so that it is only created once; and
Is it a reasonable expectation that a given compiler will do so.
I think the answer to the second question is "No", because I don't see the point of doing a huge amount of control flow analysis to save the programmer the trouble of typing the word static. However, I've often been surprised what optimizations people spend their time writing (as opposed to the optimizations which I think they should be working on :-) ). All the same, I would strongly recommend using the word static if that's what you wanted.
For the first question, there are circumstances under which the compiler could perform the optimization based on the "as-if" rule, but in very few cases would it work out.
First of all, if any object or subobject in the initializer has a non-trivial constructor/destructor, then the construction/destruction is visible, and this is not an example of copy elision. (This paragraph is C++ only, of course.)
The same would be true if any computation in the initializer list has visible side-effects.
And it should go without saying that if any subobject's value is not constant, the computation of that subobject would need to be done on each construction.
If the object and all subobjects are trivially copyable, all the initializer-list computations are constant, and the only construction cost is that of copying from a template into the object, then the compiler still couldn't perform the optimization if there is any chance that the addresses of more than one live instance of the object might be simultaneously visible. For example, if the function were recursive, and the object's address was used somewhere (hard to avoid for an array), then there would be the possibility that the addresses of two of these objects from different recursive invocations of the function might be compared. And they would have to compare unequal, since they are in fact separate objects. (And, now that I think of it, the function would not even need to be recursive in a multi-threaded environment.)
So the burden of proof for a compiler wishing to optimize that object into a single static instance is quite high. As I said, it may well be that a given compiler actually attempts to perform that task, but I definitely wouldn't expect it to.
The compiler would almost certainly do whatever is deemed most optimal, but most likely it will have it in read-only memory and turn your local variable into a pointer that points to the array in read-only memory. This assumes your array is equivalent to a POD type (or a class composed of POD types; if your class does something non-trivial and/or modifies other things, there is no way the compiler can fairly do this optimization).
I know that, in C++, when you write
int i;
you can not make any assumptions about the value that the variable will hold until you effectively assign it a value. However, if you write
int i = int();
then you have the guarantee that i will be 0. So my question is, isn't it actually an incosistency in the behavior of the language? I mean, if I have defined a class MyClass and write
MyClass myInstance;
I can rest assured that the default constructor without parameters of the class will be called to initialize myInstance (and the compiler will fail if there is none), because that's how the RAII principle goes. However, it seems that when it comes to primitive types, resource acquisition is not initialization anymore. Why is that?
I don't think that changing this behavior inherited from C would break any existing code (is there any code in the world that works on the assumption that no assumption can be made about the value of a variable?), so the main possible reason that comes to my mind is performance, for example when creating big arrays of primitive types; but still, I'd like to know if there is some official explanation to this.
Thanks.
No. It is not inconsistency.
What if your class is defined as:
struct MyClass
{
int x;
float y;
char *z;
};
then this line does NOT do that you think it does:
MyClass myInstance;
Assuming the above is declared inside a function, it is same as:
int x; //assuming declared inside a function
In C++, the types are broadly divided into 3 kinds viz. POD, non-POD, Aggregates — and there is a clear distinction between them. Please read about them and their initialization rules (there are too many topics on them. Search on this site). Also read about static initialization and dynamic initialization.
The real reason, at least initially, was that C++ wanted all
objects which are compatible with C to behave exactly as they
would in C. The reason in C was (and still is) performance;
zero initialization of objects with static lifetime was free
(because the OS must initialize all memory that it gives the
process anyway, for security reasons); zero initialization
otherwise costs runtime. (The performance rationale is less
strong today than it was originally, because compilers are a lot
better at determining that the variable will be initialized
later, and suppressing the zero-initialization in such cases;
but they do still exist; in particular, in cases like:
char buffer[1000];
strcpy( buffer, something );
If zero initialization were required, I don't know of any
compiler which would be able to skip it here, even though it
won't be necessary.)
If you write
int i;
then the initialization or not depends on the context.
Namespace scope → zero-initialized.
Local function scope → uninitialized.
Class member: depends on the constructors, if any.
The lack of initialization for a local variable is just for efficiency. For a very simple function that is called repeatedly at the lowest levels, this can matter. And C and C++ are languages used to construct the bottom levels of things.
When you set a local variable in a function to some value, then every time the function is called, the assignment takes place and the value is loaded into the stack.
For example:
void func()
{
int i = 0; // Every time `func` is called, '0' is loaded into the stack
...
}
This is something that you might want to avoid, in particularly since the C and C++ languages are also designated for real-time systems, where every operation matters.
And by the way, when you declare MyClass myInstance, you can indeed rest assure that the default constructor is called, but you can choose whether or not you want to do anything in that constructor.
So the C and C++ languages allow you to make the same choice for primitive-type variables as well.
Sometimes, we can use tools like valgrind to find out if we forgot to initialize a pointer variable. But why don't modern compilers relieve us from this common mistake which is hard to reproduce?
Initialization is not always desirable:
For performance reasons; initializing memory takes time which may not be necessary. There are even algorithms that depend on constant time allocation to achieve their desired performance (initialization is linear time). D recognizes this but has a different (probably better) approach; variables are initialized by default but has special syntax to prevent initialization.
Sometimes there is no correct default value. Static analysis or runtime debugging features can help detect when a variable is used without initialization. Simply assigning some (incorrect) value to them by default could hide a bug that would be detected using these.
There are several aspects to your question. First of all, the standard doesn't mandate this behavior. But where it wouldn't violate the standard it's probably possible. In fact debug builds, e.g. in MSVC, do quite the opposite and initialize not with 0 but with some magic value - another magic value is used to fill "freed" memory. Again, this is specific to debug builds and can help detect certain classes of errors while it might hide other bugs or obscure there whereabouts in a code base.
But I think the performance issue weighs more here. If you were to initialize integers and floats, why not all kinds of structs or arrays both on the heap and on the stack? The problem with this is of course that if I write my program and allocate a buffer to read data into it, why should I waste time to zero the buffer first if I know I'm going to read x bytes and the buffer is only x bytes long?
I agree, relying on this "random" behavior like in the Debian SSH disaster wasn't correct, but it shows that people rely on the existing behavior and consequences of changes to this behavior will not always be obvious.
Not exactly. Apart from the reasons presented in the other answers, I'd like to point out that:
a) Global variables, static local variables are always initialized, if not explicitly, then implicitly zero.
b) For a custom class `class Test`, creating a new instance by `Test *ptr=new Test()` or `Test test;` gives an initialized object.
To sum up, things that end up in '.data' '.bss' sections of ELF file are initialized either explicitly or implicitly ( zero ). Other variables in primitive types that doesn't lie in the area mentioned above has undefined content before explicit initialization (depends on your compiler). This is because, the ELF file itself provides a way to initialize variables in a) kind at very low cost, while initializing variables in stack, heap, etc, can be a terrible overhead.
You might argue that class Object might be more costly to initialize. But, above all, omitting initialization for primitive types is how things works in C and therefore C++ comply with it.
In my program, I've got a bunch of classes that will only ever have one created instance for the duration of the program. They are created only once on initialization, and destroyed only once on closing.
These classes all tend to present really broad functionality that is used by many different parts of the program, and so having them as global externs is really clean and easy to understand, rather than encapsulating them in another class or passing around pointers.
The program is multi-threaded, and all of these classes contain their own mutex for access.
Are there any problems with this approach? If so, what are the recommended alternatives.
Use a singleton pattern as follows:
Foo& foo() { static Foo x; return x; }
This is completely thread-safe. See here: G++ 4.6 -std=gnu++0x: Static Local Variable Constructor Call Timing and Thread Safety
It is guaranteed by the current standard.
Furthermore this is superior to static initialized global variables because if you have multiple of the above they will be initialized lazily in the correct dependency order.
Foo& foo() { static Foo x; return x; }
Bar& bar() { static Bar x; return x; }
and in Bar::Bar there is a call to foo(), then the Foo singleton will be created before Bar.
If I had of used global variables:
// Foo.cpp
Foo foo;
// Bar.cpp
Bar bar;
No such ordering is guaranteed.
3.6.2 Initialization of non-local variables
...the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit....
You can use a Singleton, but be sure of thread safety. For a tutorial, take a look at SINGLETON PATTERN - 1. THREAD SAFETY
An example would be
static SomeSingleton* getInstance()
{
lock_mutex();
if(!pInstance_)
pInstance_ = new SomeSingleton();
unlock_mutex();
return pInstance_;
}
By using global variables in your classes you make them difficult to test. Their behaviour now depends on a global state, which makes it difficult to reason about them. One class depends on the global variable. Another class depends on it, too. Both can change the state of the global variable any time. In essence you have a created a mutual dependency between both classes. With every access to the global variable you are one step closer to one version of the dependency hell.
You have mentioned that you do not want to pass them around as pointers. Actually I would prefer that method. By explicitly passing a dependency (your global variables) to a method or constructor you tell the world about it. If you need to pass ten dependencies to your method, you might want to rethink your solution. It might be a lot of work, but helps to improve the architecture of your program.
You have written that your classes "tend to present really broad functionality". This might be an indicator that they should be broken down into smaller components, so that you only have to pass around the functionality that you actually need.
My advice is that
you should avoid using global variables, especially in the form of singletons
try to find out more about dependency injection to properly pass around your dependencies
watch video Don't look for things (Clean Code Talks, Misko Hevery)
c++ has big problems with order of calling global objects constructors
somebody calls it "global initialization fiasco"
It's not related with multithreading, but related with initialization
If your program has many global objects then it may cause some problems (of course there are some methods to solve that problem)
You can use pattern 'singleton' but I'm not sure will it be useful in your case
Given a variable foo of type FooClass* and a member variable in that class named bar, is the distance between foo and &(foo->bar) the same in any situation with some constraints:
FooClass is a non-POD type.
We know that foo will always point to an instance of FooClass, and not some subtype of it.
We only care about behaviour under a single compiler and a single compilation; that is, the value this may result in under gcc is never used in code compiled with MSVC, and it is never saved to be re-used between compilations. It is computed in the binary and used in the binary, and that is it.
We don't use a custom new, although some instances of the class may be stack-allocated and some heap-allocated.
There is no explicit ctor for FooClass; it relies upon the compiler-generated one (and each of the fields in FooClass is either POD or default-constructable).
I can't find a guarantee either way on this in the standard (nor did I expect to), but my rudimentary testing with gcc leads me to believe that it will always be the case there. I also know that this guarantee is made for POD-types, but let us assume this type can't be POD.
An update/clarification: this is just for a single compilation of a single binary; the calculated offsets will never leave that single execution. Basically, I want to be able to uniquely identify the fields of a class in a static map and then be able to lookup into that map for some macro/template/EVIL trickery. It is merely for my own amusement, and no life support machines will rely on this code.
After you have compiled your program, Yes*.
The offset will remain constant.
There is one very important restriction, however: foo must be pointing specifically to a FooClass object. Not a class derived from FooClass, or anything else for that matter.
The reason that C++ makes the POD distinction regarding member offsets is because both multiple inheritance and the location (or lack of) a vtable pointer can create situations where the address of an object is not the same as the address of that object's base.
Under a single compiler where the compiler settings are always the same and there is nothing added to or taken away from FooClass, then yes, the distance between the address stored at foo and &(foo->bar) will always be the same, or the compiler wouldn't be able to generate proper code that worked across compilation units.
However, once you add anything to the class, or change the compiler settings, all bets are off.
As far as I know, this should always be the case, POD class or not. At compile time, based on the compiler, architecture, settings, etc., the compiler determines the size of the class and the offsets of all its members. This is then fixed for all instances of the class in the compilation unit (and by extension the linked unit, if the one-definition rule is preserved).
Since the compiler treats type pointers literally, even if the underlying type is wrong (eg: the pointer has been c-style cast incorrectly), the computed distance between &foo and &(foo.bar) will be the same, since the offset is known statically at compile time.
Note: This has definitely been done before, effectively. See, for example, Microsoft's ATL data binding code using their 'offsetof' macro...
I'm no expert but i gonna try answering you anyway :)
FooClass is a non-POD type. This mean it could have more than one sections of private, public or protected. Within such a section, the order is that of the definition of the members, but across those sections, order is arbitrary and unspecified.
foo will always point to FooClass. Well so we have guarantee there is no offset adjustment done. At least in one compilation, offsets will be the same then (don't have the backing up Standard quote. But it can't work if they were different).
We only care about behavior on a single compiler. Well since the order of members is unspecified across sections of access modifiers and the compiler is allowed to put padding between members, this won't buy us much.
We only care about objects on the stack (automatic storage duration). Well i don't see how that changes anything of the object layout.
So after all i don't think you have any guarantee that the offset will be constant across compilations. For considerations within one compilation (so if we would play with a compiler whose generated code uses an ABI that changes with each different compilation), the offset just can't be different. But even if you know the offset, you can't access the member. Your only way to access a member is using the member access operator -> and . (that's said in 9.2/9).
Why not use data member pointers? They allow accessing members safely. Here is an example: (looking up members by name).
There are two things off the top of my head that will affect the internal layout of an object:
the size of member objects. Hopefully you'll recompile all affected modules if you change a member definition.
packing pragmas may change the padding added between members. Be sure that the packing is the same for all modules that use the class, or at least the section where the class is defined. If you don't, you'll have bigger problems than unpredictable offsets.
Bottom line: If this class contains anything other than PODs, then you can make absolutely no assumptions about the offsets. If the class is just a collection of public PODs, then you're safe.
Here is a link to a portion of a chapter in an excellent intermediate C++ book. I recommend everyone to read this book if you're serious about C++.
This particular excerpt addresses a portion the question presented here:
http://my.safaribooksonline.com/0321321928/ch11?portal=oreilly
For the rest of the details, check out the book. My "bottom line" above is a simplistic summary of this chapter.
Yes, the offset is determined at compile-time, so as long as you're not comparing offsets across compilations or compilers, it will always be constant.