C++ std::list segmentation fault with different compiling order

39 views Asked by At

I have the following testing program:

// manager.h
#pragma once

#include <list>

namespace testapp
{
    class Manager
    {
    public:
        static Manager& instance();
        void addItem(int val);

    private:
        std::list<int> m_items;
    };

    template <int N>
    class Helper
    {
    public:
        Helper()
        {
            Manager::instance().addItem(N);
        }
    };
}

// manager.cpp
#include "manager.h"

namespace testapp
{
    static Manager s_global_instance;
    Manager& Manager::instance()
    {
        return s_global_instance;
    }

    void Manager::addItem(int val)
    {
        m_items.push_back(val);
    }
}

// main.cpp
#include <iostream>
#include "manager.h"

namespace testapp
{
    Helper<1> helper;
}

int main()
{
    std::cout << "It works!\n";
}

When I build this app with the following command line:

g++ main.cpp manager.cpp -std=c++2a -o TestApp

I got Segmentation fault, which is triggered in m_items.push_back(val).

However, if I build this app with different source order:

g++ manager.cpp main.cpp -std=c++2a -o TestApp

The program works as expected. I can the output It works! without any error.

After some investigation, I found that the problem is s_global_instance seems not fully initialized when Helper<1> helper gets instantiated. What I mean here is the member std::list<int> m_items is not initialized (properly) when global static variable s_global_instance is used. When addItem gets called, I stepped into push_back, I found that the head node is not actually initialized. It gets initialized after addItem getting called.

If I change static Manager s_global_instance to a local static variable like this:

Manager& Manager::instance()
{
   static Manager _instance;
   return _instance;
}

It's always working. No segmentation fault no matter which command line I use as showing above. The source file order doesn't matter any more.

My questions are here:

  • Why compiling order matters when global static variable is used?
  • Why local static variable works?
  • Is this issue related to template instantiation?
  • What is the initialization order when static variable, global static variable, global variable and template involved?
0

There are 0 answers