0

Is there a robust way to write a class that has a static member variable when that object itself has static variables of its own?

In the example provided below, where Bar has a static variable of type Foo, and Foo has a static variable of type string, I am getting a segfault when bar.cpp is compiled before foo.cpp.

How can I structure this so that it works no matter the order in which the files are provided?

foo.h

#ifndef FOO
#define FOO
#include <string>

class Foo {
public:
  static const std::string STATIC_FOO;
  Foo(): m_foo(STATIC_FOO) {};
  std::string m_foo;
};

#endif

foo.cpp

#include <string>
#include "foo.h"
const std::string Foo::STATIC_FOO = "foo";

bar.h

#ifndef BAR
#define BAR
#include "foo.h"

class Bar {
public:
  static Foo s_foo;
};

#endif

bar.cpp

#include "foo.h"
#include "bar.h"
Foo Bar::s_foo;

main.cpp

#include <iostream>
#include "bar.h"

int main() {
  Bar b;
  std::cout << b.s_foo.m_foo << std::endl;
}

This compiles fine when I specify foo.cpp before bar.cpp:

$ g++ -std=c++11 main.cpp foo.cpp bar.cpp -o main
$ ./main
Foo!

But if bar.cpp is compiled first, I get a segmentation fault:

$ g++ -std=c++11 main.cpp bar.cpp foo.cpp -o main  # note bar.cpp comes before foo.cpp here
$ ./main
Segmentation fault (core dumped)
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Evan Smith
  • 97
  • 7
  • 2
    Use a proper [_Singleton_](https://stackoverflow.com/questions/1008019/c-singleton-design-pattern?r=Saves_AllUserSaves) instead. What you're experiencing is the [**Static Initialization Order Fiasco**](https://en.cppreference.com/w/cpp/language/siof) – πάντα ῥεῖ Apr 12 '23 at 18:07
  • 3
    The problem is called [Static Initialisation Order Fiasco](https://en.cppreference.com/w/cpp/language/siof). C++ imposes no order in which translation units are compiled, which means you cannot rely that one global object in one file exists when creating another in a different file. Using Meyer's singleton instead of global/static objects is a good workaround to avoid this issue (or, better yet, try to avoid global objects altogether) – Yksisarvinen Apr 12 '23 at 18:09
  • 1
    Terminology note: Both compile "fine". Logic errors are outside the compiler's area of concern. – user4581301 Apr 12 '23 at 18:13

0 Answers0