1

I have three files:

api.h:

class HttpApi{
 public:
    static bool postData(string json);

 private:
    static  string remoteHost;
    static  string port;
    static  string url;
};

api.cpp:

string HttpApi::remoteHost = Config::getInstance().getRemoteServer();
string HttpApi::port = Config::getInstance().getPort();
string HttpApi::url="/api/miner";

bool HttpApi::postData(string json)
{
    //Here I print Config::getInstance.getRemoteServer(), the value is correct set here

    cout<<"Start resolve "<< remoteHost<<"   "<<port<<endl;
    cout<<"Succeed in resolving "<<endl;

}

and finally:

int main(int argc, char** argv)
{
    Config&  config = Config::getInstance();
    cout<<"Start loading configuration "<<endl;
    config.loadConfig("config.ini");

    HttpApi::postData("hello world");
}

The problem for me is that the initialization of two members remoteHost, port is invalid: at runtime, both are empty.

Here Config is a singleton class and it reads values from config.ini. It has some members, such as remoteHost, and port.

Why are both static members empty and how can I fix it?

YSC
  • 38,212
  • 9
  • 96
  • 149
shijie xu
  • 1,975
  • 21
  • 52
  • 2
    [Static Initialization Order Fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order), perhaps? You haven't shown the code for `Config`. – Fred Larson May 09 '18 at 15:01
  • The initialisation of `HttpApi::remoteHost` and `HttpApi::port` probably happens too early and at that time `Config::getInstance().getRemoteServer()` returns and empty string for whatever reason. Check that first. – Jabberwocky May 09 '18 at 15:01
  • Refet to this https://stackoverflow.com/questions/1563897/c-static-constant-string-class-member – Honey Yadav May 09 '18 at 15:11
  • The initialisation of static member objects very much depends on how the whole thing is compiled. The first thing standard says is: The static members are initialised in the order of their definition but not declaration. The second thing standard says is: The static initialisation can occur before the first use of any object or function of the class. – Archie Yalakki May 09 '18 at 15:22
  • This may help: https://stackoverflow.com/a/1008289/3807729 – Galik May 09 '18 at 15:55
  • Possible duplicate of [How to initialize private static members in C++?](https://stackoverflow.com/questions/185844/how-to-initialize-private-static-members-in-c) – ivan_pozdeev May 09 '18 at 19:29

1 Answers1

2

Since you haven't provided a Minimal, Complete, and Verifiable example, one can only guess what happens.

First, static data member of classes are initialized at the very beginning of your program, in an unspecified order, before main() is invoked1. This means that

string HttpApi::remoteHost = Config::getInstance().getRemoteServer();
string HttpApi::port = Config::getInstance().getPort();

is evaluated before

config.loadConfig("config.ini");

Secondly, if we make the assumption that Config::getInstance() returns a default constructed instance before any loadConfig is called, and if we also assume a default constructed Config is only a collection of, say, empty strings, then we can say for sure that HttpApi::remoteHost and HttpApi::port will be initialized from empty strings.

Finally, a possible solution would be to drop the anti-pattern Singleton is, or define a way for HttpApi to use an already loaded configuration:

void HttpApi::load(Config const& conf) // obviously declared as static
{
    remoteHost = conf.getRemoteServer();
    port       = conf.getPort();
}

int main(int argc, char** argv)
{
    Config& config = Config::getInstance();
    std::cout << "Start loading configuration\n";
    config.loadConfig("config.ini");
    HttpApi::load(config);
    HttpApi::postData("hello world");
}

1) This is not entirely true, for curious readers:

[class.static.data]/6

Static data members are initialized and destroyed exactly like non-local variables ([basic.start.static], [basic.start.dynamic], [basic.start.term]).

and

[basic.start.dynamic]/4

It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred.

YSC
  • 38,212
  • 9
  • 96
  • 149