Avihai Marchiano
Avihai Marchiano

Reputation: 3927

global static const string won't get initialized

Running c++ on Ubuntu.

in configuration.h file i have this (global):

static const string APP_CONFIG_FILE_NAME = "cfg";

in my configuration.cpp (which is singleton by the way, so load configuration is called by constructor of Configuration) i do this:

void Configuration::loadConfiguration() {
    cout<< "config file name "  << APP_CONFIG_FILE_NAME.data();
        load();
}

The load configuration will be called from another global: (this is the key point for the failure)

Timer t(Configuration::Instance()->timeout);

i see that the cost string is not initialized (empty). If i replace the string with char* its initialized in my expected order.

However on another program the same classes for configuration work, so i dont know the problem.

There is another question but not the same since there its not a global.

Upvotes: 4

Views: 4081

Answers (2)

justin
justin

Reputation: 104708

It gets initialized, of course. However, it is likely being initialized in the order you don't want/expect it initialized in.

Specifically, it is probably not constructed by the time you use it because you use it during construction of another global.

Unfortunately, you don't have a good way to portably specify initialization order of global data. Initialization order among multiple files is not defined by the standard, although it is likely specified by your toolchain. Consequently, altering the order of compilation or building using another toolchain can result in a different initialization order. Search for "static initialization order fiasco" for more details.

One way to avoid this issue is to declare your static data in a function:

const std::string& AppConfigFileName() {
  static const std::string name("cfg");
  return name;
}

Although...I don't see why this must be static (the function above allows you to return by value -- no need for static). Plus, I don't see why this could not be a plain C string, since you just treat it as a C string in your config loader.

Upvotes: 10

James Kanze
James Kanze

Reputation: 154047

The key issue is when Configuration::loadConfiguration is called. The order of initialization between translation units is undefined, so if Configuration::loadConfiguration is called from the constructor of a static object in another translation unit, the variable may not have been constructed. In this particular case, the simplest solution is just to change the type to char const[]; this allows static initialization, which occurs before any dynamic initialization. (Any initialization which involves non-trivial constructors is dynamic.) More generally, you could use the singleton pattern for the string.

Several other points are worth mentioning as well:

  • You've declared a static instance of an object in a header file. This means that every translation unit which includes the header file will have a separate instance of the object. This is probably not a good idea.

  • You output APP_CONFIG_FILE_NAME.data(). This is simply the data in the std::string object—it is not guaranteed to be '\0' terminated. When you need a '\0' terminated string, you must use std::string::c_str(). (But in this case, you can just output the std::string. There's no need for any function call on it.)

Upvotes: 2

Related Questions