Your program works correctly (if it is compiled as a single file) if you delete this line:
static volatile S &S_instance = S::instance();
OK When building on my machine without your S_instance declaration:
0000000000400d86 <__static_initialization_and_destruction_0(int, int)>: 400d86: 55 push %rbp 400d87: 48 89 e5 mov %rsp,%rbp 400d8a: 48 83 ec 10 sub $0x10,%rsp 400d8e: 89 7d fc mov %edi,-0x4(%rbp) 400d91: 89 75 f8 mov %esi,-0x8(%rbp) 400d94: 83 7d fc 01 cmpl $0x1,-0x4(%rbp) 400d98: 75 43 jne 400ddd <__static_initialization_and_destruction_0(int, int)+0x57> 400d9a: 81 7d f8 ff ff 00 00 cmpl $0xffff,-0x8(%rbp) 400da1: 75 3a jne 400ddd <__static_initialization_and_destruction_0(int, int)+0x57> 400da3: b8 b8 40 40 00 mov $0x4040b8,%eax 400da8: 0f b6 00 movzbl (%rax),%eax 400dab: 84 c0 test %al,%al 400dad: 75 2e jne 400ddd <__static_initialization_and_destruction_0(int, int)+0x57> 400daf: b8 b8 40 40 00 mov $0x4040b8,%eax 400db4: c6 00 01 movb $0x1,(%rax) 400db7: be 00 00 00 00 mov $0x0,%esi 400dbc: bf b0 40 40 00 mov $0x4040b0,%edi 400dc1: e8 3c 05 00 00 callq 401302 <boost::scoped_ptr<S>::scoped_ptr(S*)> 400dc6: b8 da 13 40 00 mov $0x4013da,%eax 400dcb: ba 90 40 40 00 mov $0x404090,%edx 400dd0: be b0 40 40 00 mov $0x4040b0,%esi 400dd5: 48 89 c7 mov %rax,%rdi 400dd8: e8 8b fd ff ff callq 400b68 < __cxa_atexit@plt > 400ddd: c9 leaveq 400dde: c3 retq
When compiling with your S_instance declaration:
0000000000400d86 <__static_initialization_and_destruction_0(int, int)>: 400d86: 55 push %rbp 400d87: 48 89 e5 mov %rsp,%rbp 400d8a: 48 83 ec 10 sub $0x10,%rsp 400d8e: 89 7d fc mov %edi,-0x4(%rbp) 400d91: 89 75 f8 mov %esi,-0x8(%rbp) 400d94: 83 7d fc 01 cmpl $0x1,-0x4(%rbp) 400d98: 75 4f jne 400de9 <__static_initialization_and_destruction_0(int, int)+0x63> 400d9a: 81 7d f8 ff ff 00 00 cmpl $0xffff,-0x8(%rbp) 400da1: 75 46 jne 400de9 <__static_initialization_and_destruction_0(int, int)+0x63> 400da3: e8 c2 04 00 00 callq 40126a <Singleton<S>::instance()> 400da8: 48 89 05 01 33 00 00 mov %rax,0x3301(%rip) # 4040b0 <S_instance> 400daf: b8 c0 40 40 00 mov $0x4040c0,%eax 400db4: 0f b6 00 movzbl (%rax),%eax 400db7: 84 c0 test %al,%al 400db9: 75 2e jne 400de9 <__static_initialization_and_destruction_0(int, int)+0x63> 400dbb: b8 c0 40 40 00 mov $0x4040c0,%eax 400dc0: c6 00 01 movb $0x1,(%rax) 400dc3: be 00 00 00 00 mov $0x0,%esi 400dc8: bf b8 40 40 00 mov $0x4040b8,%edi 400dcd: e8 3c 05 00 00 callq 40130e <boost::scoped_ptr<S>::scoped_ptr(S*)> 400dd2: b8 e6 13 40 00 mov $0x4013e6,%eax 400dd7: ba 90 40 40 00 mov $0x404090,%edx 400ddc: be b8 40 40 00 mov $0x4040b8,%esi 400de1: 48 89 c7 mov %rax,%rdi 400de4: e8 7f fd ff ff callq 400b68 < __cxa_atexit@plt > 400de9: c9 leaveq 400dea: c3 retq
In the last code, you can clearly see that the constructor for static scoped_ptr occurs after S_instance.
The following were compiled:
#include <cstdio> #include <boost/scoped_ptr.hpp> #include <boost/thread/once.hpp> #include <boost/noncopyable.hpp> template <class T> class Singleton : public boost::noncopyable { public: static T& instance() { boost::call_once(init, flag); return *t; } static void init() { t.reset(new T()); } private: static boost::scoped_ptr <T> t; static boost::once_flag flag; }; template <class T> boost::scoped_ptr<T> Singleton<T>::t(0); template <class T> boost::once_flag Singleton<T>::flag = BOOST_ONCE_INIT; class S : public Singleton<S> { public: void p() { printf("hello");} }; // static volatile S &S_instance = S::instance(); int main() { S &ss = S::instance(); ss.p(); }