More Meyers Singleton woes with VC++

Started by
13 comments, last by level10boy 21 years, 8 months ago
Ok, I''ve bit the bullet and made the destructor public but now I have a new problem. Everything is fine until I hit Release build with maximum speed optimizations turned on. The constructor for my Meyers singletons gets called twice, which I find hard to believe as it doesn''t happen with any other build type. The object basically gets constructed twice. I must say I cannot see why this is hapenning and am totally mistified. Any advice or answers will be much appreciated.
Advertisement
Hmmm... Make sure you do NOT inline the getInstance()
method or "funny things could happen". Remember, in debug
build, inlining is turned OFF .


Kami no Itte ga ore ni zettai naru!
神はサイコロを振らない!
Thankyou oh so much, I stopped the Instance method from being inlined and it totally solved the problem. Can you explain exactly why this fixed it.

Thanks
It''s quite simple actually. When you inline a method,
the actual code is copy & pasted by the compiler to
replace the function call. So if your getInstance() is
copied twice or more, you''ll get many instances of your
"singleton".

In general, it''s a BAD idea to inline methods that
contain static data for exactly that reason.


Kami no Itte ga ore ni zettai naru!
神はサイコロを振らない!
In case somebody doesn't know what I was talking about in
the previous post, I forgot to mention that the Meyers
Singleton is usually implemented as:


    // In Singleton.hclass Singleton    {    public:        static Singleton &getInstance(void);    }// end// In Singleton.cppSingleton &Singleton::getInstance(void)    {    static Singleton s_Singleton;    return s_Singleton;    }// end    


[Edit: changed getInstance() to static]


Kami no Itte ga ore ni zettai naru!

[edited by - tangentz on July 29, 2002 10:31:22 AM]
神はサイコロを振らない!
quote:Original post by tangentz
It''s quite simple actually. When you inline a method,
the actual code is copy & pasted by the compiler to
replace the function call. So if your getInstance() is
copied twice or more, you''ll get many instances of your
"singleton".

In general, it''s a BAD idea to inline methods that
contain static data for exactly that reason.


That is close but not quite right. The problem is not with the inline, but static.

Static variables inside inline functions share the same variable throughout the whole program. (section 7.1.4.2)

Static functions ( deprecated now, should be functions in unnamed namespaces) are defined inside each translation unit. Therefore, the static keyword is causing the multiple definition of the function.

Consider this.

inline void Shared()
{
static int shared; // external linkage, whole program share same instance
}

// note: deprecated, use unnamed namespace instead
static void Local()
{
static int local; // internal linkage, every cpp file have an instance of this
}


For a inlined static class member function, the linkage should be external. Unless you are using an very old compiler which is confused by the inline and static but I don''t think VC++ 6 is one of them. Perhaps level10boy who like to paste his test case.

Ps. Your meyer singleton is wrong. I believe you need to declare getInstance as a static member function, unless you are showing a different variant.
static works differently on member functions than on global functions, and there aren''t any global functions here. I would have thought the compiler would have been smart enough to realise that the function had static variables and would refuse to inline it though...

If I had my way, I''d have all of you shot!

codeka.com - Just click it.
quote:Original post by Void
That is close but not quite right. The problem is not with the inline, but static.


Err, but the problem is inline and static.

quote:
Static variables inside inline functions share the same variable throughout the whole program. (section 7.1.4.2)


True, in theory. But some "popular" compilers don''t conform
to this. Scott Meyers talks about it in Effective C++ and
More Effective C++. I know this because I experienced the
exact same thing. We''re talking VC++ here...

quote:
Consider this.
inline void Shared()
{
static int shared; // external linkage, whole program share same instance
}


Not if the compiler is "faulty". Shared() is copied as
many times as it is inlined, causing multiple instances
of the static variables to be present. See MEC++. The only
way to be sure is to make Shared() non-inline.

quote:
// note: deprecated, use unnamed namespace instead
static void Local()
{
static int local; // internal linkage, every cpp file have an instance of this
}


Sorry, but this is wrong. A static function exists ONLY
in the translation unit (CPP) where it is compiled in. You
can''t even extern and use it, because it has internal linkage.
Only ONE instance of this is present.

quote:
For a inlined static class member function, the linkage should be external. Unless you are using an very old compiler which is confused by the inline and static but I don''t think VC++ 6 is one of them. Perhaps level10boy who like to paste his test case.


Unfortunately, VC++ 6 is one of them.


Kami no Itte ga ore ni zettai naru!
神はサイコロを振らない!
quote:Original post by Dean Harding
static works differently on member functions than on global functions, and there aren''t any global functions here. I would have thought the compiler would have been smart enough to realise that the function had static variables and would refuse to inline it though...


VC++ 6 (don''t know about 7) would gladly inline functions with
static variables (BAD idea!).




Kami no Itte ga ore ni zettai naru!
神はサイコロを振らない!
quote:Original post by tangentz
VC++ 6 (don''t know about 7) would gladly inline functions with
static variables (BAD idea!).


Wow, I never knew that I''ll try it out on VS.NET later on and see if it''s fixed...

If I had my way, I''d have all of you shot!

codeka.com - Just click it.

This topic is closed to new replies.

Advertisement