472,348 Members | 1,255 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,348 software developers and data experts.

Wrong static initialization order

Hello everybody, my first message on this forum. I tried to solve my issue by reading other similar posts, but I didn't succeed. And forgive me if this mail is so long.

I'm trying to achieve the following (with incomplete succes): I want in a given namespace Parameters a list of "initializers" (which are objects derived from a simple interface that can be implemented anywhere, and are used to define which parameters the program will take at command line) to be registered before the main starts, or better, before a function parse(argv, argc) of the namespace Parameters is called (from the main). The goal is that I to have such initializers to be called in some automatic way.

The working solution:

Each initializer is a static variable (placed in the file to which the initializer belongs) derived form a virtual class "ParametersInitializer", and its constructor calls a function Parameters::registerInitializer() passing its own pointer. Inside registerInitializer I keep track of the pointers inside a simple linked list, by storing its head and tail as static variables inside Parameters.cpp. When calling parse(), and hence when every initialization went right (especially the std::map I use to store the parameters) I call some function for each registered initializer which adds the parameters.

Now, what I want is to use an object for this list. It does not work neither with std::list nor with a very simple list object I wrote. The problem seems to be the order of initialization of static variables, which I know is not defined between different files. But I assumed that whenever a static variable is accessed, it must had been previously initialized. Which seems not to be the case.

I tried to condensed my problem in the following files:
Expand|Select|Wrap|Line Numbers
  1. /********************************************************************/
  2. Parameters.h
  3. /********************************************************************/
  4. #ifndef PARAMETERS_H
  5. #define PARAMETERS_H
  6.  
  7. // This is the prototype for the Initializers to be stored at creation time
  8. // and, later on, used by parse()
  9. class ParametersInitializer {
  10. public:
  11.         ParametersInitializer();
  12.         virtual ~ParametersInitializer();
  13. };
  14.  
  15. // Namespace for parameter parsing
  16. namespace Parameters {
  17.         // Function for registering initializers in the list
  18.         void registerInitializer(ParametersInitializer * aInitializer);
  19.  
  20.         // Command line parser
  21.         void  parse(int argc, char ** argv);
  22. };
  23.  
  24. #endif
  25.  
  26. /********************************************************************/
  27. Parameters.cpp
  28. /********************************************************************/
  29. #include <iostream>
  30. #include "Parameters.h"
  31. #include "PointerList.h"
  32.  
  33. // List of the initializers
  34. static PointerList Initializers;
  35.  
  36. ParametersInitializer::ParametersInitializer()
  37. {
  38.         // I would like to register here, but then it will acces virtual function
  39.         // Parameters::registerInitializer(this);
  40. }
  41.  
  42. ParametersInitializer::~ParametersInitializer()
  43. {
  44. }
  45.  
  46. void Parameters::registerInitializer(ParametersInitializer * aInitializer)
  47. {
  48.         // Registers the initializer in the static PointerList object
  49.         Initializers.store((void *) aInitializer);
  50.         cout << "Registering. Now there are " << Initializers.size() << " registered Initializers" << endl;
  51. }
  52.  
  53. void Parameters::parse(int argc, char ** argv)
  54. {
  55.         cout << "Parsing..." << endl;
  56.         // Prints the number of registered initializers
  57.         cout << "There are " << Initializers.size() << " registered Initializers" << endl;
  58.  
  59.         // Does the parsing of argc argv, code omitted
  60. }
  61.  
  62. /********************************************************************/
  63. PointerList.h
  64. /********************************************************************/
  65. #ifndef POINTERLIST_H
  66. #define POINTERLIST_H
  67.  
  68. #include <iostream>
  69. using namespace std;
  70.  
  71. // This should store pointers in a linked list
  72. // In this example just stores the size of such list
  73.  
  74. class PointerList{
  75. public:
  76.         PointerList() : count(0)
  77.         {
  78.                 cout << "Creating a PointerList object" << endl;
  79.         }
  80.  
  81.         void store(void * pointer)
  82.         {
  83.                 count++;
  84.         }
  85.  
  86.         int size()
  87.         {
  88.                 return count;
  89.         }
  90. private:
  91.         int count;
  92. };
  93.  
  94. #endif
  95.  
  96. /********************************************************************/
  97. somefile.cpp
  98. /********************************************************************/
  99. #include <iostream>
  100. #include "Parameters.h"
  101.  
  102. using namespace std;
  103.  
  104. // Derives from ParametersInitializer
  105. class Initializer_B : public ParametersInitializer {
  106. public:
  107.         Initializer_B()
  108.         {
  109.                 cout << "Creating an object of type Initializer_B" << endl;
  110.                 Parameters::registerInitializer(this);
  111.         }
  112. };
  113.  
  114. // Three static variables, for which the constructor will be called
  115. static Initializer_B tmp1;
  116. static Initializer_B tmp2;
  117. static Initializer_B tmp3;
  118.  
  119. /********************************************************************/
  120. main.cpp
  121. /********************************************************************/
  122. #include <iostream>
  123. #include "Parameters.h"
  124.  
  125. using namespace std;
  126.  
  127. // Derives from ParametersInitializer
  128. class Initializer_A : public ParametersInitializer {
  129. public:
  130.         Initializer_A()
  131.         {
  132.                 cout << "Creating an object of type Initializer_A" << endl;
  133.                 Parameters::registerInitializer(this);
  134.         }
  135. };
  136.  
  137. // Static variable, for which the constructor will be called
  138. static Initializer_A tmp1;
  139. static Initializer_A tmp2;
  140.  
  141. // Main function
  142. int main(int argc, char ** argv)
  143. {
  144.         // Parses arguments
  145.         Parameters::parse(argc, argv);
  146.  
  147.         return EXIT_SUCCESS;
  148. }
  149.  
As you notice, in this example there are 5 static initializers: two of type Initializer_A in main.cpp and three of type Initializer_B in somefile.cpp (obviously there should be just one static variable for each derived initializer, this is just an example).

Now, if I compile these files (the compiler is gcc version 4.0.1 for Mac) and run the program, I obtain the following output:

Creating an object of type Initializer_B
Registering. Now there are 1 registered Initializers
Creating an object of type Initializer_B
Registering. Now there are 2 registered Initializers
Creating an object of type Initializer_B
Registering. Now there are 3 registered Initializers
Creating a PointerList object
Creating an object of type Initializer_A
Registering. Now there are 1 registered Initializers
Creating an object of type Initializer_A
Registering. Now there are 2 registered Initializers
Parsing...
There are 2 registered Initializers

As you can see, first the three Initializer_B static objects are created, then the static object PointerList, and finally the two Initializer_A static objects. And therefore three initializers are lost. Obviously you may have different outcomes, since the order is undefined. But I expected PointerList to be the first, since both Initializer_A and Initializer_B access the static object PointerList (from register()).

Is gcc's fault? Or is the order undefined nomatter which object access whichother? I know that the order of initialization is unspecified among different files, but I assumed that if static A uses static B, then static B will be initialized first (or in other words, that when a static object is accessed it have been already initialized).

How can I make all this working? Is the only option to manage such a list by simple static variables (with constant initializers) and directly from within Parameters.cpp?

Anoter (smaller) problem is that I have to call the function "registerInitializer" from the constructor of each derived class, because if I call it from the constructor of the base class "ParametersInitializer" (which would be a much cleaner solution), then when I access the pure virtual function he does not access those of the derived class, but the virtual ones (with a runtime errror). Any way out?

Thanks and sorry again for the long mail,
Sandro Bosio
Mar 14 '07 #1
1 3342
This is an update on my own message.

First forget about the fact that I cannot register the initializer from the constructor of the base class ParametersInitializer. Indeed now I do, I don't know why I had problems with virtual functions before (but I had them), now they seem to have disappeared.

I found out that having the PointerList object as a static member of ParametersInitializer partially solves the issue. Doing so and compiling the files, one obtains the proper initialization order (which is PointerList first), probably because the compiler finds out that such a order is needed (while before the need for initialization was hidden in a call to a function).

However, the problem still remains. When Parameters.cpp is compiled in a library, which is then linked when compiling main.cpp and somefile.cpp, then again the initialization order can fail (it happens to me at least). So, the question is still valid. Can I assume that whenever I access a static object it has been previously initialized, or I cannot?

However, I found a satisfying solution, which is having as static variable a pointer to a list (std::list or any other implementation), with a constant initialization NULL, and creating the list when at the first call of registerInitializer().

Best,
Sandro
Mar 15 '07 #2

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: Qin Chen | last post by:
I will present very long code, hope someone will read it all, and teach me something like tom_usenet. This question comes to me when i read...
5
by: Luther Baker | last post by:
Hi, Is the order of initialization guaranteed for static members as it is for instance members? Namely, the order they appear the in the...
3
by: DanielBradley | last post by:
Hello all, I have recently been porting code from Linux to cygwin and came across a problem with static const class members (discussed below). I...
4
by: Bret Pehrson | last post by:
I just stumbled across the following problem: //.h class Masses { static double mass1; static double mass2; static double mass3; };
5
by: BigMan | last post by:
Does the standard define the order in which static members of a class are created and initialized?
5
by: Jesper Schmidt | last post by:
When does CLR performs initialization of static variables in a class library? (1) when the class library is loaded (2) when a static variable is...
10
by: n.torrey.pines | last post by:
Are global variables (and const's) guaranteed to be initialized before static class members (and methods) ? const int x = 19907; int get_x() {...
3
by: Steve Folly | last post by:
Hi, I had a problem in my code recently which turned out to be the 'the "static initialization order fiasco"' problem...
20
by: JohnQ | last post by:
The way I understand the startup of a C++ program is: A.) The stuff that happens before the entry point. B.) The stuff that happens between the...
1
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
0
jalbright99669
by: jalbright99669 | last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
2
by: Matthew3360 | last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
0
by: Arjunsri | last post by:
I have a Redshift database that I need to use as an import data source. I have configured the DSN connection using the server, port, database, and...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific...
0
by: Matthew3360 | last post by:
Hi, I have been trying to connect to a local host using php curl. But I am finding it hard to do this. I am doing the curl get request from my web...
0
Oralloy
by: Oralloy | last post by:
Hello Folks, I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA. My problem (spelled failure) is with the...
0
by: Carina712 | last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand....

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.