G++ получает неправильный порядок уничтожения статических переменных

У меня есть следующие классы, которые пытаются реализовать общий Singleton.

struct BaseObject
{
   virtual ~BaseObject() {}
};
class _helper
{
private:
    template<typename T> friend class Singleton;
    set<BaseObject*> _s;
    static _helper& _get()
    {
        static _helper t;
        return t;
    }
    _helper()
    {
        cout<<" _helper ctor"<<endl;
    }
    ~_helper()
    {
        cout<<" _helper dtor"<<endl;
        //assert(_s.empty());
    }
};

// Singleton<foo>::Instance() returns a unique instance of foo
template <typename T>
class Singleton : virtual private T
{
public:
    static T& Instance()
    {
        static Singleton<T> _T;
        return _T;
    } 

private:
    Singleton()
    {
        cout<<"inserting into helper "<<typeid(T).name()<<" ptr "<<this<<endl;
        assert(!_helper::_get()._s.count(this));
        _helper::_get()._s.insert(this);
    }
    ~Singleton()
    {
        cout<<"erasing from helper "<<typeid(T).name()<<" ptr "<<this<<endl;
        assert(_helper::_get()._s.count(this));
        _helper::_get()._s.erase(this);
    }
};

Теперь, если я вызову Singleton< bar>::Instance()с последующим Singleton< foo>::Instance(), я должен увидеть следующий вывод:

 inserting into helper 3bar ptr 0x509630  
 _helper ctor  
 inserting into helper 3foo ptr 0x509588  
 erasing from helper 3foo ptr 0x509588  
 erasing from helper 3bar ptr 0x509630  
 _helper dtor  

Однако в некоторых случаях я вижу следующее:

 inserting into helper 3bar ptr 0x509630  
 _helper ctor  
 inserting into helper 3foo ptr 0x509588  
 erasing from helper 3bar ptr 0x509630  
 _helper dtor  
 erasing from helper 3foo ptr 0x509588  

Обратите внимание, что во втором случае barи fooбыли уничтожены в том же порядке, в котором они были построены. Похоже, это происходит, когда одиночные экземпляры fooи barсоздаются внутри разделяемой библиотеки (.so )как статические ссылки :

static bar& b = Singleton<bar>::Instance();   
static foo& f = Singleton<foo>::Instance();   

. Есть идеи, почему это нужно делать?

10
задан Ross Rogers 2 May 2012 в 20:27
поделиться