2

In my application, there are 2 global objects. One object’s constructor it accesses the other one assuming it is already created. Fortunately my application was running correctly for some time. But due to the recent changes in cpp files and compilation order, I figured out that the global object creation order has been changed from what my application was expected.

So, My question is,

Is there a way to control the creation order of global objects. I think the same issue should be there for static objects as well. According to my tryouts I identified that the linking order or “o” files changes this. But is it correct? Isn't there a proper way of doing this?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Sujith Gunawardhane
  • 1,251
  • 1
  • 10
  • 24

3 Answers3

4

Ignoring the fact that global variables are not a very good idea, you can wrap the objects inside of functions. This way, they get created when they are first accessed, giving you control over creation order:

Foo& get_foo()
{
  static Foo f;
  return f;
};

Bar& get_bar()
{
  static Bar b(get_foo());
  return b;
}

Example of use:

int main() {
    Bar& b = get_bar();
    return 0;
}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • But then, can these objects accessed by some other places as usual static / global objects? – Sujith Gunawardhane Jul 11 '14 at 15:52
  • 3
    @SujithGunawardhane - the can be accessed by calling the above functions. – Anon Mail Jul 11 '14 at 15:54
  • 1
    Lower-overhead solution: Just define all run-time initialized interdependent objects in the same compilation unit in dependency order. Bonus: You get the proper destruction order for free (compared to slight overhead with wrapping in functions). – Deduplicator Jul 11 '14 at 16:01
  • @Deduplicator, I doubt there's any overhead, any decent compiler will optimize the function call out since it never changes. – Blindy Jul 11 '14 at 16:37
  • @Blindy: How? The purpose of wrapping the global as a static in an accessor function was delaying initialization until first use and thus avoiding the static initialization order fiasco. – Deduplicator Jul 11 '14 at 16:40
  • @Deduplicator, turns out we were both right, VC++ 2012 optimizes the function call out, but adds a boolean test (`jne`) before using the value that calls or skips the `static` initialization. So yeah, there is a bit of overhead. – Blindy Jul 11 '14 at 17:02
1

A nice maintainable way would be to create global pointers to these objects and assign them in a single function (such as main() or elsewhere) in the desired order. If you were instead to do "lazy-evaluation" and simply let the objects be created upon access, then it will be much less obvious what order they are in, and thus less maintainable.

This does of course mean that you will have null pointers if they are not initialized.

if A's ctor must use object B, then A should assert that B is not null.

(edit: That is not say that lazy-evalutaion doesn't have its place, but for this situation I'd personally go with pointers)

Brandon
  • 483
  • 3
  • 12
0

Check out the Singleton pattern (as copied from yolinux). There's a few variations out there, but the idea is to have creation specified at the first usage of the class as accessed via Instance(), which is then used to access the only instance of the class anywhere else in code.

class Singleton{
public:
  static Logger* Instance(){
    if(!m_pInstance) return new Singleton;
    return m_pInstance;
  }

private:
  Singleton(){};  // Private so that it can  not be called
  Singleton(Singleton const&){};             // copy constructor is private
  Singleton& operator=(Singleton const&){};  // assignment operator is private
  static Singleton* m_pInstance;
};

This part should go outside the header (best if in body file):

Singleton::Singleton* m_pInstance = NULL;
kwierman
  • 441
  • 4
  • 11