singleton question

B

ben chang

i'm hacking at some code originally written for VC++, trying to port to
linux GCC 4. the linker returns multiple-definition errors with a
singleton object, which i guess is not a problem in visual c++. i'll try
to excerpt the relevant parts without posting all the source files (it's
the maya exporter for the Ogre 3D engine).

there's a pretty standard-looking Singleton template, and in a file called
"materialSet.h" we have a class using it:

/////
namespace OgreMayaExporter
{
class MaterialSet : public Singleton<MaterialSet>
{
(nothing unusual in here, so i won't bore you... )
};

template<> MaterialSet Singleton<MaterialSet>::ms_Singleton=0;
}

/////

now, materialSet.h is included directly or indirectly by a bunch of source
files (blendshape.cpp, ogreExporter.cpp, skeleton.cpp, mesh.cpp). so i get
this linker error:

g++ -c -I. -I../include -I/usr/autodesk/maya/include -I/usr/X11R6/include -I/usr/local/include/OGRE -pipe -D_BOOL -DLINUX -DI386 -ffast-math submesh.cpp
g++ -shared -o OgreExport blendshape.o material.o mesh.o ogreExporter.o paramlist.o particles.o skeleton.o submesh.o -L/usr/autodesk/maya/lib -lOpenMaya -lOgreMain
mesh.o:(.bss+0x0): multiple definition of `OgreMayaExporter::Singleton<OgreMayaExporter::MaterialSet>::ms_Singleton'
blendshape.o:(.bss+0x0): first defined here
ogreExporter.o:(.bss+0x0): multiple definition of `OgreMayaExporter::Singleton<OgreMayaExporter::MaterialSet>::ms_Singleton'
blendshape.o:(.bss+0x0): first defined here
skeleton.o:(.bss+0x0): multiple definition of `OgreMayaExporter::Singleton<OgreMayaExporter::MaterialSet>::ms_Singleton'
blendshape.o:(.bss+0x0): first defined here
submesh.o:(.bss+0x0): multiple definition of `OgreMayaExporter::Singleton<OgreMayaExporter::MaterialSet>::ms_Singleton'
blendshape.o:(.bss+0x0): first defined here

this declaration is complicated enough that it's a bit hard to wrap my
head around, but isn't this essentially repeatedly declaring a global
(within the namespace) variable, which is what Singletons are supposed to
avoid? is this a difference between gcc and msvc?

thanks,

-ben
 
R

Rolf Magnus

ben said:
i'm hacking at some code originally written for VC++, trying to port to
linux GCC 4. the linker returns multiple-definition errors with a
singleton object, which i guess is not a problem in visual c++. i'll try
to excerpt the relevant parts without posting all the source files (it's
the maya exporter for the Ogre 3D engine).

there's a pretty standard-looking Singleton template, and in a file called
"materialSet.h" we have a class using it:

/////
namespace OgreMayaExporter
{
class MaterialSet : public Singleton<MaterialSet>
{
(nothing unusual in here, so i won't bore you... )
};

template<> MaterialSet Singleton<MaterialSet>::ms_Singleton=0;

The above line defines Singleton<MaterialSet>::ms_Singleton. If this is in a
header and that header is included in multiple files, you'll get multiple
definitions of that object.
this declaration is complicated enough that it's a bit hard to wrap my
head around, but isn't this essentially repeatedly declaring a global
(within the namespace) variable, which is what Singletons are supposed to
avoid?

It's repeatedly _defining_ the very same namespace-level variable, which any
program is supposed to avoid. Put the definition into an implementation
file, not a header.
 
J

James Kanze

i'm hacking at some code originally written for VC++, trying to port to
linux GCC 4. the linker returns multiple-definition errors with a
singleton object, which i guess is not a problem in visual c++. i'll try
to excerpt the relevant parts without posting all the source files (it's
the maya exporter for the Ogre 3D engine).
there's a pretty standard-looking Singleton template, and in a file called
"materialSet.h" we have a class using it:
/////
namespace OgreMayaExporter
{
class MaterialSet : public Singleton<MaterialSet>
{
(nothing unusual in here, so i won't bore you... )
};
template<> MaterialSet Singleton<MaterialSet>::ms_Singleton=0;

What is this line supposed to be doing? If the template
Singleton is written correctly, it shouldn't be necessary. As
it is, you're defining an explicit specialization of a template
data member (presumably static). Explicit specializations
aren't templates, however, they're instantations of templates,
and thus normal classes, functions or data. You wouldn't expect
defining normal data like this in a header file to work, and
that's really what you're doing. (The result is a multiple
definition, a violation of the one definition rule, and thus
undefined behavior. Most compilers will complain in the link
phase, but no diagnostic is actually required.)

I'm not sure why you're declaring the instance anyway.
Normally, depending on the variant of singleton you're using,
the instance is either a local variable of the
Singleton::instance function, or allocated dynamically. In the
latter case, the Singleton template might declare a pointer as a
static, in which case, the header which defines the template
would require something like:

template< typename T >
T* Singleton< T >::eek:urInstance = 0 ;

Note that unlike your definition, this is also a template (and
not an explicit instantiation), and so should behave like all
templates, with multiple definitions being allowed (as long as
they are the same), and the compiler ensuring that everything
works as if there were a single definition for each
instantiation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,810
Latest member
Kassie0918

Latest Threads

Top