Static variable definition order in c++ - c++

Hi i have a class tools which has static variable std::vector m_tools.
Can i insert the values into the static variable from Global scope of other classes defined in other files.
Example:
tools.h File
class Tools
{
public:
static std::vector<std::vector> m_tools;
void print()
{
for(int i=0 i< m_tools.size() ; i++)
std::cout<<"Tools initialized :"<< m_tools[i];
}
}
tools.cpp File
std::vector<std::vector> Tools::m_tools; //Definition
Using register class constructor for inserting the new string into static variable.
class Register
{
public:
Register(std::string str)
{
Tools::m_tools.pushback(str);
}
};
Different class which inserts the string to static variable in static variable
first_tool.cpp
//Global scope declare global register variable
Register a("first_tool");
////////
second_tool.cpp
//Global scope declare global register variable
Register a("second_tool");
Main.cpp
void main()
{
Tools abc;
abc.print();
}
Will this work?
In the above example on only one string is getting inserted in to the static list. Problem look like "in Global scope it tries to insert the element before the definition is done"
Please let me know is there any way to set the static definiton priority? Or is there any alternative way of doing the same.

You are likely, here, to encounter the issue referred to as Initialization Order Fiasco.
The problem is that the initialization order of globals (and static class variables are globals) is well-defined within a same translation unit (roughly, think .cpp) but is completely undefined across translation units. Therefore, there is no guarantee that the vector be initialized when you try to push items in there.
Your solution here ? Use local static variables:
class Tools
{
public:
static std::vector<std::string>& AccessTools()
{
static std::vector<std::string> Tools; // local static
return Tools;
}
private:
};
class Register
{
public:
Register(std::string str)
{
Tools::AccessTools().push_back(str);
}
};
It is guaranteed to be initialized upon first access... though it's not (and cannot be) thread safe; if you are in a multithreading situation, you need to call Tools::AccessTools in main before launching the other threads to guarantee the initialization.

The initialization order of static global variables in different compilation units is not defined in C++ - this is why you have a problem.
A workaround may be to call a static function which contains the first static variable as local. This way you can force it to be initialized before it is used:
// tools.h
class Tools
{
public:
static std::vector<std::vector>& getTools();
...
};
// tools.cpp
std::vector<std::vector>& Tools::getTools() {
static std::vector<std::vector> tools;
return tools;
}
...
class Register
{
public:
Register(std::string str)
{
Tools::getTools().pushback(str);
}
};

The initialization of statics is not specified by C++. C++ FAQ Lite call it the "static initialization order fiasco"
my2c

Related

C++ static members, multiple Objects

I've got some trouble with static members and methods in C++.
This is the Class header:
class Decoration {
public:
//Static Methods
static void reloadList();
//Static Members
static std::unordered_map<int, Decoration> decorationMapID;
};
And in .cpp:
void Decoration::reloadList() {
sqlTable result = db->exec("SELECT id, name, description FROM decorations");
for(sqlRow r: result) {
Decoration::decorationMapID.insert(std::pair<int,Decoration>(atoi(r[0].c_str()), Decoration(r[1], r[2], atoi(r[0].c_str()))));
}
}
Now, in my mainWindow class (I'm using QT5), I call reloadList() and initialize the map.
The list is now filled in this Object.
In another Window-Class, I want to use this static list, but the list is empty. Could you explain how I have to use the static members to access the same list everywhere?
Declaration of second class:
in mainWindow.h:
ShoppingLists slDialog;
in mainWindow.cpp I call:
slDialog.setModal(true); slDialog.show();
Btw.: The whole thing is a CocktailDatabase, so my target is to have a List/Map for Cocktail-, Ingredient-, Decoration-, and Taste- Objects, which I can use without reloading it from SQLite.
1) The static member exists only once and is shared between all the instances of Decoration.
2) The question is why it is empty. Here some hints:
a) You think it is empty because some windows object was not refreshed and is not aware that your list was poupulated.
b) Your window get initiaslised before the static list is initialised
3) nevertheless an advice: don't make your static list public, especially if it has to be initialised before it's used. Use a public access function that makes sure it's initialised. Here the rough idea:
class Decoration {
public:
std::unordered_map<int, Decoration> getMap();
protected: // or even private ?
static void reloadList();
static bool loaded=false;
static std::unordered_map<int, Decoration> decorationMapID;
};
where getMap() would be something like:
if (!loaded) {
... // load the list here
loaded = true;
}
return (decorationMapID);
You are using the default-constructed value of the static variable before it had a chance to be populated. If you put breakpoints in the code that uses the value and the code that initializes it, you'll see that the latter is called after the former.

How to change Visual Studio C++ initialization sequence for const string arrays in statically linked libraries

I'm making some changes to a legacy application (CWinApp) in Visual Studio 2013, that uses a legacy statically linked library. I'm having problems in getting const string arrays initialized in the application.
To make things easier, I've created a basic example that demonstrates the issue. The example consists of a CWinApp application (class CTestApp), that references static library MyLib.lib. CTestApp owns an object of type MyClass that's defined in MyLib. Here are some code extracts:
Main Application (CTestApp)
TestApp.h:
class CTestApp : public CWinApp
{
// --- Standard Wizard generated CWinApp stuff here ---
private:
MyClass mine;
};
TestApp.cpp:
// --- Standard Wizard generated CWinApp stuff here ---
CTestApp::CTestApp()
: mine(55)
{
}
Static Library (MyLib.lib)
MyClass.h:
#pragma once
#include <string>
const std::string ids[] =
{
"ABC",
"DEF",
"GHI"
};
const int num_ids = 3;
class MyClass
{
public:
MyClass(int id);
private:
int id;
std::string name;
};
MyClass.cpp:
#include "MyClass.h"
MyClass::MyClass(int id)
: id(id)
{
for (int i = 0; i < num_ids; ++i)
{
name += ids[i];
}
}
The problem is that when stepping through CTestApp::CTestApp into MyClass::MyClass, I find that the strings in array ids are empty. What's also strange is that the integer constant num_ids is initialized to 3 as expected. This seems to only happen for const string arrays declared in static libraries. If I declare a similar array within CTestApp itself, it is initialized by the time I step into CTestApp::CTestApp.
I also find that if I run the application and break in CTestApp::InitInstance then ids has been initialized correctly.
Is there a way to force Visual Studio to initialize const string arrays such as this before entering the member initialization section of CTestApp::CTestApp?
Not really. You can probably solve your specific case, though.
ids is a global variable with dynamic initialization.
So is your global CTestApp object.
ids is defined everywhere that includes the header. The app object is probably defined in some main file.
The order of dynamic initialization of globals in different modules (.cpp files) is unspecified by C++. It can differ from compilation to compilation, from compiler to compiler. You don't want to depend on it.
If you need to guarantee an order, the only way is to put the initialization into the same module. A single module is initialized in order of declaration.
So the solution for your specific case is: declare ids as extern in the header, and actually define it alongside your global app, just before. However, that doesn't scale as you get more classes.
Alternatively, make ids a true constant by changing it to an array of const char*. That would make it get initialized statically, which happens before dynamic initialization.
Finally, you could change mine to a (smart) pointer and only initialize it in InitInstance.

Global variable gets different values when used in different static methods

I have the following class that implements static methods that must use a single global array. It is defined as such:
//Defined in LockTrack.h file
enum LOCK_ID{
LOCKID_0,
LOCKID_1,
LOCKID_2,
LOCKID_COUNT
};
static LOCK_ID __glob_lock_ids[LOCKID_COUNT];
class CLockTrack
{
public:
static void getLockedLocks(/*parameters*/)
{
//__glob_lock_ids = points to 0x015ef558 address in memory
LOCK_ID lockID = __glob_lock_ids[0];
}
static void inline setLock(LOCK_ID lockID)
{
//__glob_lock_ids = points to 0x015ef330 address in memory
__glob_lock_ids[lockID] = LOCK_ON_FLAG;
}
};
But what happens is that the '__glob_lock_ids' pointer points to different memory locations in each method. Why? And how to fix this?
Nope, that's not a global. Change it to
extern LOCK_ID __glob_lock_ids[LOCKID_COUNT];
and move
LOCK_ID __glob_lock_ids[LOCKID_COUNT];
into a single implementation file. Your version, static, will effectively create a new variable for each translation unit that includes the header.

How can I initialize class variables in a header?

I'm writing a library where the user can define arbitrary structures and pass them to my library, which will then obtain the memory layout of the structure from a static member such structure must have as a convention.
For example:
struct CubeVertex {
// This is, per convention, required in each structure to describe itself
static const VertexElement Elements[];
float x, y, z;
float u, v;
};
const VertexElement CubeVertex::Elements[] = {
VertexElement("Position", VertexElementType::Float3),
VertexElement("TextureCoordinates", VertexElementType::Float2),
};
C++ best practices would suggest that I move the static variable and its initialization into my source (.cpp) file. I, however, want to keep the variable initialization as close to the structure as possible since whenever the structure changes, the variable has to be updated as well.
Is there a portable (= MSVC + GCC at least) way to declare such a variable inside the header file without causing ambiguous symbol / redefinition errors from the linker?
Consider a simple getter.
struct CubeVertex {
static const std::array<VertexElement, N>& GetElements() {
static const std::array<VertexElement, N> result = {
//..
};
return result;
}
//..
}
Immediate benefit: No array-to-pointer-decay.
What you could do here is using an anonymous namespace.
Wrap everything into "namespace { ... };" and you can then access CubeVertex::Elements like you normally do.
However, this creates a new instance of the static data everytime you include the headerfile, which adds to the executable's filesize.
It also has some limitations on how to use the class/struct, because you cannot call functions of that class from another file (which won't be a problem in this special case here).

Is it ok to use a static variable to initialize/register variables?

Language: C++
Toolkit: Qt4
The toolkit I'm using has a static method called int QEvent::registerEventType() to register my own event types. When I subclass this QEvent I need to supply the base class this value. QEvent::QEvent(int type).
Is it ok to use a static variable to call this before application starts? Consider the following:
//This is all in my .cpp file
static int myEventType; //This will contain my registered type
/*If I create a static instance of this class the constructor
gets called before the main() function starts.
*/
class DoRegisterMyEventType {
public:
DoRegisterMyEventType() {
myEventType = QEvent::registerEventType();
}
};
static DoRegisterMyEventType doRegisterMyEventType;
//Here is the constructor for MyEvent class which inherits QEvent.
MyEvent::MyEvent()
: QEvent(myEventType)
{
}
How 'evil' is this? I could wrap the whole thing in a namespace to prevent polluting the global namespace.
Since C++'s initialization across TUs is a big grey area with much implementation leeway, I prefer to scrap it completely and be explicit about what gets done when. (This rejection of initialization order due to lack of guarantees is similar to how singleton classes reject global objects.) Specifically, this means any global state (global variables, static data members, and function-local statics) that cannot be initialized with constant-expressions must be initialized in exactly one TU, and that TU is the one that implements main.
In the manual case, this means inserting and updating code in the translation unit that contains main and in main itself. The most common example of such code is calling srand(time(0)) to seed the std::rand PRNG.
You can refactor that manual code management using the preprocessor:
// the implementation file for main, could be named main.cpp
#include "whatever_declares_the_real_main.hpp"
#include "global_objects.inc"
int main(int argc, char* argv[]) try {
#include "main_init.inc"
return the_real_main(argc, argv);
// main.cpp has well-defined responsibility:
// initialize global state before passing control to another function, and
// handle return-code or exceptions
// you can modify this, depending on your preference and desired API
// for example:
return the_real_main(std::vector<std::string>(argv+1, argv+argc));
return the_real_main(parse_args(argv+1, argv+argc));
// just make sure to keep main.cpp's responsibility well-defined and
// relatively simple
}
// example handling; depending on your specifics, you might do something
// different, or know how to provide more information:
catch (std::exception& e) {
std::cerr << "abnormal termination: " << e.what() << '\n';
return 1;
}
catch (...) {
std::cerr << "abnormal termination.\n";
return 1;
}
These .inc files are neither headers nor implementation files. The exact file extension doesn't matter as long as you don't use something which is commonly used for headers or implementation files, such as .h, .hpp, .cc, .cpp, and so forth. You can generate global_objects.inc and main_init.inc based off file-naming conventions, using include guards so that dependencies may be included (just as include guards work for headers).
For example, both of these files correspond with myevent.hpp and would be placed alongside that header:
// file "myevent.global_inc"
#ifndef INCLUDE_GUARD_37E6F5857F8F47918A7C83F29A9DA868
#define INCLUDE_GUARD_37E6F5857F8F47918A7C83F29A9DA868
#include <QEvent.hpp> // or whatever headers you need
#include "myevent.hpp" // declares the variable defined just below
// (remember you use 'extern' to declare objects without defining them)
int your_namespace::myEventType = QEvent::registerEventType();
#endif
// file "myevent.main_inc"
#ifndef INCLUDE_GUARD_4F1B93D0F4D3402B802CBA433241AA81
#define INCLUDE_GUARD_4F1B93D0F4D3402B802CBA433241AA81
// nothing needed in this case, from what you've shown so far
// this is where you place expressions that would otherwise require a dummy
// global variable to make sure they are executed, but this also allows use
// of temporary variables while includes handle dependency order:
#include "something_else.main_inc" // fake example dependency, which must
{ // be executed first
int temp;
some_func(&temp);
other_func(temp); // not easy to transform this into a global's init
// expression, yet defining it this way is natural, because it's exactly
// how you would do it inside a function
}
#endif
Note that if you only require static data initialization with constant-expressions, then that is preferred over all other techniques. The primary restriction for that initialization is not being able to make a function call (but it's actually more complex), so it doesn't apply in your case; this is the only kind of global variable initialization that C can do, if you want to find out more.
Static level initialization is a huge compiler-dependent grey area, as others have mentioned. However, function level initialization is not a grey area and can be used to your advantage.
static inline int GetMyEventType()
{
static int sEventType = QEvent::registerEventType();
return sEventType;
}
MyEvent::MyEvent()
: QEvent(GetMyEventType())
{
}
This solution has the property that registerEventType is guaranteed to be called before you need your event type even if you construct MyEvent during static initialization, which is good, but it does open you up to thread-safety issues if it's possible for MyEvent to be constructed on multiple threads.
Here's a thread-safe version, based on boost::call_once:
#include "boost/thread/once.hpp"
static boost::once_flag sHaveRegistered = BOOST_ONCE_INIT; //This is initialized statically, effectively at compile time.
static int sEventType = -1; //-1 is not a valid event
static void DoRegister()
{
sEventType = QEvent::registerEventType();
}
static inline int GetMyEventType()
{
boost::call_once(sHaveRegistered, &DoRegister);
return sEventType;
}
I use the "static register object" pattern quite a bit, but you must be aware of one big problem - you must ensure that the thing you are registering with, which itself is likely to be static, is created before the thing you are registering. As C++ does not guarantee the order of static construction between translation units, this can be problematic. One solution is to use the so called Meyer Singleton:
class Registry {
public:
static Registry & Instance() {
static Registry r;
return r;
}
...
private:
Registry() {
...
}
};
As all references to the Registry must go through the Instance() method, you are guaranteed the required construction order.