why the c++ constructor was not called when it appear as the static member variable?
Asked Answered
T

4

7

I had a strange problem ,

declare a static member variable whose name is B class in A class . And initialize in the cpp file. but the constructor of B class was never called. I try to use some small test , the test constructor could be called normally. so it is very strange for our production system.

The code like this , in hpp:

class Test
{
    public:
    Test()
    {
        ofstream file("/tmp/wup.txt",ios::app);
        file << "wup in test" << endl;
        file.close();
    }
};

//## An extended personality
class TsdNAExtPersonality : public TsdNAPersonality{
public:

  TsdNAExtPersonality(
        s_gg62_personRec * gg62Header,
                   TsdNAFunctionType requiredFunctionType);
private:
  static Test test;

public:
  TsdNAExtPersonality( string * personalityFile, TsdNAFunctionType requiredFunctionType);
};

And in another cpp file I initialize with

Test TsdNAExtPersonality::test;

I have tried in several way, but i found all of ways are unusefull.

  1. did not set the variable as member variable but as global variable ==> also can't output
  2. change the member variable as pointer and change the initialize way as using new ==> no

the environment is HP-UX ,and the compile is aCC

so my question are :

  1. is there any compile option will influence the variable ? in other words, all the static variable will not be initialized.

  2. from the standard of C++ it should be called when the library was load, right?

  3. I put another static int value using the same way, it could be initialized. but the class constructor is not called , very strange.

  4. is there any mistake in my code ?

Thereafter answered 13/9, 2013 at 16:16 Comment(11)
SSCCE here gives the same result if you don't init. the variable. This SSCCE does indeed run the constructor for the static variable.Militarist
Are you sure the constructor is not called? Are you sure it's not just a matter of you not having permission to do what you are trying to do? What happens if you place the code from your constructor directly in your main function?Croft
@BenjaminLindley stole my comment - it's almost surely not that the constructor is being lost, but rather that you can't complete the particular file operation. Did you check for errors in your ofstream object [it's not listed in the sample]?Butyraceous
Note that the constructor runs for the static variable before main, so if you're hoping that the constructor for the static variable will produce some effect on created objects' states in main, it will not happen like that.Militarist
@BenjaminLindley I'm sure the constructor was not called, as i set another variable for example i = 4, and i found i was still 0.Thereafter
@Militarist quite agree with you, i have do the same test with the similiar code. besides i also tested in the way split as main executable binaray and library . it also work. but put the code in my production system , the constructor was not called at all.Thereafter
@Butyraceous i delete the ofstream and use the variable with int, the varaible was not initialized at all.Thereafter
@Militarist thanks, seems reasonable. so i can't create any object before main? i did not test the scenario.Thereafter
@ANewStar Yeah, an example. It would be a global variable though. As long as your object creation happens before the static initialization.Militarist
@Militarist thanks, i will try with your last suggestion tha is to declare another global variable to force the static initializatioin . do i understand correctly?Thereafter
@ANewStar That static init is happening, I'm just saying if your static variable's class constructor will not be able to affect objects created after it.Militarist
U
9

from the standard of C++ it should be called when the library was load, right?

No. Dynamic initialisation of an object with static storage duration is guaranteed to happen before execution of any function defined in the same translation unit. If there are no such functions, or your program never calls them, then there's no guarantee that it will ever be initialised.

I put another static int value using the same way, it could be initialized. but the class constructor is not called , very strange.

An int variable is initialised statically, before the program starts, as long as its initialiser is constant.

is there any compile option will influence the variable ?

Not that I know of, but I'm not familiar with your platform. You could give yourself more control over the object's creation by scoping it within a function:

static Test & test() {
    static Test test;
    return test;
}

Now it is guaranteed to be initialised the first time the function is called. Of course, you'll need to remember to call it at some point.

Unific answered 13/9, 2013 at 16:31 Comment(2)
i did not put it into the method, as i will read the file content and it will cost time. So i want to initialized when the library was load.Thereafter
As i did not find the best solution, i changed my code and put the variable into the function then it was initialized normally as i expect.Thereafter
K
1

The startup and shutdown of a C++ program are sort of grey areas because it's not clear how much of your code you can already use (because it has been initialized) and how much is yet starting. At shutdown the same happens for destructor... it's not clear how many subsystems have been already shut down when your static instances are destroyed.

Moreover you should never use static initialization for anything that may fail, debugging before the start or after the end of main can be very difficult.

Note also that the order in which statics are initialized is not defined (except relative to other statics in the same compilation unit) and it may change from one compilation to the next. This means that you may live happy with a working program until for some strange reason you get a different initialization order and things stop working without any relevant change in the code.

Using static initialization for extremely simple things is ok, for anything else is not and you should do instead proper controlled initialization.

Knacker answered 13/9, 2013 at 16:33 Comment(1)
Just initialize the subsystems explicitly in main in a controlled order and shut down them orderly when quitting. Using implicit or lazy construction seems a nice approach and it may work for simple cases... if the project grows however it's a model that can bite back badly.Knacker
P
0

Static initialization in C++ is:

  • Zero initialization
  • Constant initialization
  • Dynamic initialization

Hence your best bet is initialization at first function call:

int fn() {
    static int result = 42;
    return result;
}

EDIT:

If you want to initialize before main:

struct Initialize { 
    Initialize() { fn(); }
}

Initialize initialize;
Plashy answered 13/9, 2013 at 16:32 Comment(1)
thanks , but i need to speed up as i want to read some file in the constructor it will cost seconds. if i put into the function the production system will be influenced.Thereafter
T
0

I think there is a bug in your compiler.

Running this simple code on linux/g++ gives the expected results:

#include <iostream>

using namespace std;

class A
{
    public:
        A() { cout << "Hallo" << endl; }
};

class B
{
    public:
    static A a;
};

A B::a;    // < here the constructor must be called!

int main()
{
   cout << "Main runs" << endl;
   return 0;
}

Results in:

Hallo
Main runs

The constructor MUST be called when the static data member is constructed (commented line above).

Talca answered 13/9, 2013 at 16:50 Comment(1)
yes, i also do the same test. the constructor was called normally.Thereafter

© 2022 - 2024 — McMap. All rights reserved.