473,738 Members | 4,774 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Wrong static initialization order

4 New Member
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 "initialize rs" (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 "ParametersInit ializer", and its constructor calls a function Parameters::reg isterInitialize r() passing its own pointer. Inside registerInitial izer 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 "registerInitia lizer" from the constructor of each derived class, because if I call it from the constructor of the base class "ParametersInit ializer" (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 3533
Sandro Bosio
4 New Member
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 ParametersIniti alizer. 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 ParametersIniti alizer 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 registerInitial izer().

Best,
Sandro
Mar 15 '07 #2

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

Similar topics

1
4623
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 <<Think in C++>> 2nd, chapter 10 , name control, section "Static initialization dependency". There is a example to show how to solve the prolem involved with a technique first poineered by Jerry Schwarz while creating the iostream library (because the definitions for cin, cout, and cerr are static...
5
1810
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 declaration? ie: foo.h:
3
3608
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 am seeking to determine whether I am programming non-standard C++ or if the problem lies elsewhere. To summarize static const class members are not being accessed properly when accessed from a DLL by another external object file (not within the DLL). It only occurs when the static const...
4
2228
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
2573
by: BigMan | last post by:
Does the standard define the order in which static members of a class are created and initialized?
5
6778
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 first referenced (3) when... It seems that (1) holds for unmanaged C++ code, but not for managed code. I have class library with both managed and unmanaged static variables that are not referenced by any part of the program. All the
10
4204
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() { return x; } // another compilation unit: int get_x();
3
5856
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 (<http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12>) The FAQ section describes a solution using methods returning references to static objects. But consider:
20
6093
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 entry point and the calling of main(). C.) main(). So, if the above is OK, does static initialization occur during A or B? What happens during A?
0
8788
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9476
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9335
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9263
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8210
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6751
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4570
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4825
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2193
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.