• Advertisement
Sign in to follow this  

Object factory and objects registration ...

This topic is 3766 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I've got a little problem with object factories and more specifically the registration of creation functions. This is how I usually do it :
// for example, in Mesh.cpp :
#include "Mesh.h"
#include "NodeFactory.h"

namespace
{
    Object * CreateMesh(void)
    {
        return(new Mesh());
    }

    const bool registered = NodeFactory::Instance()->Register("Mesh", &CreateMesh);
}

class Mesh
{
    // ....
};
I found this method in "Modern C++ Design" by Andrei Alexandrescu, and until recently, it worked perfectly. But now, I'm compiling my engine as a static library, and it doesn't work anymore. When I set a breakpoint in the Register method of the NodeFactory, it is never reached ... Why is that ? And is there a way to solve this problem ?? Thx in advance.

Share this post


Link to post
Share on other sites
Advertisement
Objects with static storage duration are only guaranteed to be initialized if they are used. Since nothing ever uses the registered variable, it's not actually guaranteed to be initialized, so your program has been depending on non-guaranteed behavior. In this case, what's probably happening is that the linker is seeing that nothing in your application that uses the static library ever uses the registered variable, it doesn't bother adding it to your application.

Bottom line, self-registration tricks like this are extremely fragile. Consider using explicit registration techniques instead.

Share this post


Link to post
Share on other sites
I think you ran into the same problem I had a while ago. It seems like the compiler is too aggressive removing unused code.
It probably sees that registered is never used and figures it can just leave out the call to Register().
I ended up creating a static array that contains all CreateXXX() function pointers that is used by the factory.

Share this post


Link to post
Share on other sites
Ok, thanks for the reply. What I still don't understand is I always used this method, with the same compiler, and almost the same source code (I just changed a few things to seperate the engine from the rest of the code and compile it as a .lib) and it's the first time I have this problem.

And I also thought that I could trust a well know book ...

Anyway, the advantage of this method is that the object factory doesn't have to #include all the objects headers, or something like this ... is there any other method that would have the same benefit ?

Share this post


Link to post
Share on other sites
I think you should keep this technic. We're using it in almost the same way on our multiplatform engine (DS, PSP, Wii, Win32) and are very pleased with it.
What we've done is simply studied each compilers we use and found tricks to not strip dead code we really needed.

Share this post


Link to post
Share on other sites
Quote:
Original post by paic
... (I just changed a few things to seperate the engine from the rest of the code and compile it as a .lib)...

That's because what SiCrane described only happens for static libraries, and not for dll's or executables (at least if you're using visual studio).

Share this post


Link to post
Share on other sites
Koen : thanks, I missed the part about static libraries in SirCrane's answer :)
skalco6 : I'd like to, but I don't really know how to make it work in my case ... maybe use registered somewhere in the code ?

Share this post


Link to post
Share on other sites
Silly hacky idea: have a 'numRegistered' global which you increment in Register(), and maybe that will stop the compiler from optimising that call away? You may need to add a function that queries that value to stop the compiler optimising that away too. ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by paic
Anyway, the advantage of this method is that the object factory doesn't have to #include all the objects headers, or something like this ...

You're not really sure, are you. See, these automatic registration thingies are sexy-sounding, but ultimately they create much more hassle than they solve.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
Silly hacky idea: have a 'numRegistered' global which you increment in Register(), and maybe that will stop the compiler from optimising that call away? You may need to add a function that queries that value to stop the compiler optimising that away too. ;)


That won't help in this situation. To the compiler/linker modifying a numRegistered global would be just the same as registering with the factory: a side effect of an initialization. Side effects of initializations will only occur if the initialization occurs, which is only guaranteed to happen with an object of static storage duration if the object is referenced.

Share this post


Link to post
Share on other sites
If your using Visual Studio 2005, here's how you can solve your problem:

Go into the properties of the .vcproj of your application (the one that link to your static lib). In the General Page of the Linker settings, there's a "Use Library Dependency Inputs" that you should set at "Yes".

This will slow down the linking process a little, because instead of linking with the .lib, the linker will use the .obj(s) your static library project produced.

Share this post


Link to post
Share on other sites
Quote:
Original post by paic
Koen : thanks, I missed the part about static libraries in SirCrane's answer :)
skalco6 : I'd like to, but I don't really know how to make it work in my case ... maybe use registered somewhere in the code ?


If you tell me what compiler you're using I can tell you the compiler trick to make it work.

Share this post


Link to post
Share on other sites
This keeps coming up, and the problem is often misunderstood. It does not lie in aggressive dead code removal, nor in the linker eliding unreferenced functions.
Instead, it is a simple implementation detail: certain object files within a .lib are not even considered for linking. Those that do not export a symbol satisfying some other module's unresolved external are dropped.

SiCrane has the word on why this behavior is allowed by C++.

For a discussion of alternatives, see "[Sweng-Gamedev] Component Objects Stripped From Static Libs".

HTH+HAND.


PS:
Quote:
If you tell me what compiler you're using I can tell you the compiler trick to make it work.
I'd be interested as to what you would suggest for VC2005 without ditching .lib files - /INCLUDE ?

Share this post


Link to post
Share on other sites
Hi again, thx for those who suggested solutions, I'll try them.
I'm using Microsoft Visual Studio 2008 Beta 2.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement