7

I have a trivial singleton class. My singleton.h file looks something like this:

class singleton
{
...
public:
    static singleton& instance();
};

And my singleton.cpp looks like this:

...
singleton& singleton::instance()
{
    static singleton * const _instance(new singleton);
    return *_instance;
}

In writing this class, I thought I was relying on thread-safe function-local static initialization, which I understand to be set out in section 6.7 of the C++ standard as described here. Hopefully I understand how this is supposed to work.

I'm running Visual C++ with the November 2013 CTP toolchain. Microsoft says November 2013 CTP supports thread-safe function-local static initialization and a quick glance at object code produced by the compiler shows it is trying to do so.

My problem is that the destruction of a static storage duration object in another translation unit requires access to singleton::instance(). I expected this would not present any difficulty because the static variable backing singleton::instance() is a pointer that is never deleted. However, calls to singleton::instance() from that other object are crashing my process and the stack trace looks like this:

_Init_thread_header
singleton::instance
other_translation_unit_object::~other_translation_unit_object

Where _Init_thread_header() appears to be inserted by the compiler to implement thread-safe static initialization.

So my question is: does the code above reveal that I'm fundamentally misunderstanding how static initialization is supposed to work (most likely case, so be nice if so :), or is it possible something else is awry?

Community
  • 1
  • 1
0xbe5077ed
  • 4,217
  • 1
  • 28
  • 62
  • 1
    This isn't your question, but your singleton's destructor will never run if you don't `delete` it. – dlf Jul 17 '14 at 19:02
  • Although the actual object pointed to by `static singleton * const _instance` will never be destroyed as your code is written, that may not be true for whatever `_Init_thread_header()` stuff the compiler inserts into `instance()` to guarantee its threadsafe initialization. I'd guess that's the source of your problem and you have a simple static destructor order issue. – dlf Jul 17 '14 at 19:06
  • @0xbe5077ed Since you're using C++11, why don't you do the singleton the easy way as described here: http://stackoverflow.com/questions/11711920/how-to-implement-multithread-safe-singleton-in-c11-without-using-mutex – PaulMcKenzie Jul 17 '14 at 19:11
  • @PaulMcKenzie, do you mean not to use a pointer? Then I run into the undefined static destruction problem. – 0xbe5077ed Jul 17 '14 at 19:15
  • 5
    @0xbe5077ed Why not simply `static singleton _instance; return _instance;`?? – πάντα ῥεῖ Jul 17 '14 at 19:17
  • @dlf, I guess a (very implicit!) part of my question is whether the standard has anything to say about whether simply attempting to "read" a static pointer after a T.U. has gone through static destruction should crash the process? – 0xbe5077ed Jul 17 '14 at 19:17
  • @πάντα ῥεῖ: the purpose of the pointer is to avoid static destruction order fiascos. If I do as you suggest, I ***definitely*** can't call `singleton::instance()` in the static destruction phase of another translation unit. Also I think it unlikely that the pointer is *per se* causing the problems I describe in my question. – 0xbe5077ed Jul 17 '14 at 19:19
  • 1
    @0xbe5077ed - Maybe you're over-engineering this. Why not write a simple function that has a static `instance` and return the instance, similar to what is outlined in the SO link in my comment and what `πάντα ῥεῖ` suggested? – PaulMcKenzie Jul 17 '14 at 19:25
  • @PaulMcKenzie, I think we're talking past each other a bit. First, because the purpose of the pointer is to avoid static destruction order problems; second, because it is difficult to see how using the pointer is causing the problem I'm describing in the question. – 0xbe5077ed Jul 17 '14 at 19:31
  • @0xbe5077ed _'static destruction order fiascos ...'_ IMHO one of the reasons, why the use of the singleton pattern is so discouraged from many parties. `(1)` If you really need to have a singleton, have only one holding **all** of the systems working instances. `(2)` If you really need to have more than one singleton, let them communicate via interfaces, not by direct `instance()` calls. – πάντα ῥεῖ Jul 17 '14 at 19:35
  • @0xbe5077ed I'm not sure what the standard has to say (maybe someone else does?), but based on your experience I think we can at least say that Microsoft does not ensure this is safe in their preview release. – dlf Jul 17 '14 at 19:38
  • Also see [Access violation on static initialization](http://stackoverflow.com/q/32517234/608639) and the cited Microsoft Connect report. – jww Feb 02 '17 at 13:10

1 Answers1

2

"Magic statics" were not implemented in the version of Visual Studio you were using. They were first implemented in Visual Studio 2015.

https://msdn.microsoft.com/en-us/library/hh567368.aspx

Colin Jensen
  • 3,393
  • 1
  • 18
  • 17
  • 1
    The poster claimed to be using VC++ November 2013 CTP, which is a later compiler than the one in Visual Studio 2013 (but an earlier one than in Visual Studio 2015). The link they posted shows that the Nov 2013 CTP is supposed to support "magic statics", while the link you posted does not say one way or the other. – Jim Oldfield May 16 '16 at 10:12