0

I have a program in which I wrote a class as follows:

.h File

typedef map<string, int> stringMap;
class SampleClass{
public:
    void setup();
    void update();
    void draw();
private:
    static stringMap _someMap;
    static stringMap someMapInitializer();
};

.cpp file

//Initializer for static var
stringMap SampleClass::_someMap = someMapInitializer();

stringMap SampleClass::someMapInitializer(){
    _someMap["something"] = 1;
    return _someMap;
}

But on doing the above, I start getting "Program received signal EXC_BAD_ACCESS" error on running the program (compiles fine though)

The above function is changed to the following:

stringMap SampleClass::someMapIntializer(){
    map<string, int> m;
    m["somehting"] = 1;
    return m;
}

works fine. What is wrong with the first case? Can't I access static member variables in a static function?

2
  • You mention "static var" in your comment, but neither _someMap nor _someMapInitializer() are declared static. Commented May 31, 2013 at 10:47
  • @NicolaMusatti : Thanks for pointing out. I typed the code in the text box myself and didn't copy paste. Corrected Commented May 31, 2013 at 12:46

2 Answers 2

3

In the first case, you try to access the object (_someMap) that you are supposed to be initializing. _someMap is not yet initialized there.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. That's kinda careless on my part. I ahve another short follow-up query though about initializer. When are the static members initialized? Since I can access the public static variables/members directly in the main.cpp without even creating an object/initializing my class, when are these actually initialized by the compiler before the main program starts?
@user1240679 I think static members are initialized when the class is loaded into memory. For all intensive purposes, you can assume that this is when the program starts, just before main is run. Dynamic class loading (the exception to the "when the program starts" rule) is a rather advanced concept, probably no need to worry about that now.
1

C++ guarantees the object _someMap with static storage duration will be initialized before any other function in the same *.cpp file is called as a (direct or indirect) result of statements in main.

But the process of initializing _someMap involves calling the function _someMapInitializer(). If that function returns, _someMap will be created using a move constructor or copy constructor, passed the returned value. But _someMapInitializer() then attempts to call a member function on the object _someMap, which is not yet constructed. Undefined Behavior.

For a fix, I'd design it more like...

class SampleClass {
    //...
private:
    static stringMap& someMap();
    static void someMapInitializer(stringMap&);
};

stringMap& SampleClass::someMap() {
    static bool init_done = false;
    static stringMap the_map;
    if (!init_done) {
        someMapInitializer(the_map);
        init_done = true;
    }
    return the_map;
}

void SampleClass::someMapInitializer(stringMap& the_map) {
    the_map["something"] = 1;
}

This is the "Construct On First Use" idiom.

Now that the only way to get at the map is to call function someMap(), there's no way anything could accidentally use it before the std::map constructor has been called and the object has been populated with its initial data.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.