Search code examples
c++constantsstatic-membersstatic-initializationstatic-order-fiasco

c++ static initialization order fiasco


I'm currently learning C++, and I'm having some troubles.

I've developped a program by using lots of #define, but I'd like to use static const instead (collision/type/scopes...).

So, I now have something like:

file1.hpp

 class A {
   public:
     static const std::string MY_CONST_VAR;
 };

file1.cpp

 const std::string A::MY_CONST_VAR = "some string";

file2.cpp

 static std::string arrayOfString[] = {
   A::MY_CONST_VAR,
   ...
  };

My code compiles with no warnings/errors (compiling with -W -Wall -Wextra -Werror flags).

However, when I try to run it, it results in a segfault.

I've ran it with valgrind, and it gave me the following ouput:

==11239== Invalid read of size 4
==11239==    at 0x5F525CB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)
==11239==    by 0x40D076: _GLOBAL__sub_I__ZN16GraphicInterface13DEFAULT_WIDTHE (GraphicInterface.cpp:42)
==11239==    by 0x51AC7C: __libc_csu_init (in /home/simon/PSU_2013_zappy/gui/gui_zappy)
==11239==    by 0x66D8E54: (below main) (libc-start.c:246)
==11239==  Address 0xfffffffffffffff8 is not stack'd, malloc'd or (recently) free'd

So, the segfault occurs during the arrayOfString instanciation. I think the problem is that the arrayOfInt is allocated before the constant. But in that case, is it possible to use static const for this purpose?

I don't know how to patch this issue. Am I doing it wrong? Is there a better way to do it? How to solve this issue?


Solution

  • Thanks to the comments, I finally solved the problem by using constexpr keyword.

    It gives me the following working code:

    file1.hpp

    class A {
      public:
        static constexpr char MY_CONST_VAR[] = "some string";
    };
    

    file1.cpp

    const char A::MY_CONST_VAR[];
    

    file2.cpp

    static std::string arrayOfString[] = {
      A::MY_CONST_VAR,
      ...
    };