Pregunta

I'm trying to use Loki::Factory in a project which is compiled with VC8 (I'm not allowed to switch to a newer compiler). I'm having an issue when the program exits, which I can reproduce with this basic code (which is the very least you might want to achieve when using a factory)

#include "stdafx.h"
#include <loki/Factory.h>

struct Base{};
Loki::Factory< Base, int> factory;

struct Derived : public Base{};
Base* buildDerived(){
    return new Derived();
}
namespace {
    bool registeredD = factory.Register(1, buildDerived);
}

int _tmain(int argc, _TCHAR* argv[])
{
    system("pause");
    return 0;
}

everything is fine up to when the system gets to a pause asking for the use to press a key (as for system("pause")); when I press the key, however, the program aborts, because of an unhandled exception, thrown from within the function

~auto_ptr()
{   // destroy the object
delete (_Ty *)_Myptr;
}

which can be found in the visual studio file "memory". The exception is an access violation and the stack starts with:

compmgr.dll!std::auto_ptr<Loki::FunctorImpl<Interface2D::IElement *,Loki::NullType,Loki::SingleThreaded> >::~auto_ptr<Loki::FunctorImpl<Interface2D::IElement *,Loki::NullType,Loki::SingleThreaded> >()  Riga 718 + 0x32 byte  C++
    compmgr.dll!Loki::Functor<Interface2D::IElement *,Loki::NullType,Loki::SingleThreaded>::~Functor<Interface2D::IElement *,Loki::NullType,Loki::SingleThreaded>()  + 0x2b byte    C++

I couldn't find any reference to the use of std::auto_ptr from Loki on the internet.

How can the problem be solved?

¿Fue útil?

Solución 2

The problem is with lifetime management. I report the solution here for reference:

#include "stdafx.h"
#include <loki/Factory.h>
#include <loki/Singleton.h>

struct Base{
    virtual ~Base(){};
};
typedef Loki::SingletonHolder< Loki::Factory<Base, int> > Factory;

struct Derived : public Base{};
Base* buildDerived(){
    return new Derived();
}
namespace {
    bool registeredD = Factory::Instance().Register(1, buildDerived);
}

int _tmain(int argc, _TCHAR* argv[])
{
    system("pause");
    return 0;
}

Otros consejos

Since i always wanted to look at Loki libraries i used this chance. Well, to start, the issue is not connected with MSVC versions, i did run the same example on VS2008 and Loki libraries build with VS2008 and had the same results. Second:

#include "stdafx.h"
#include <loki/Factory.h>
#pragma comment(lib, "loki_D.lib")
struct Base{};


struct Derived : public Base{};
Base* buildDerived(){
    return new Derived();
}

int _tmain(int argc, _TCHAR* argv[])
{
    Loki::Factory< Base, int> factory;
    bool registeredD = factory.Register(1, buildDerived);
    //system("pause");
    return 0;
}

This works fine. I examined the crash at your example and seems that the Factory is deleting the association container where the functor you created is supposed to be after it is already destroyed. Seems to me that this is because Loki is hooking up atexit() and deleting some stuff there (not sure why, I guess to handle Singleton objects), that is where your Functor gets deleted, and then after the the destructor of your factory is called and then the erase call on the association container fails. Well - if it's not a huge deal, don't make the factory a global object. If it is a huge deal, try to debug and find why Loki is doing the stuff it does in atexit, maybe you need to set up something more. But at least as far as I can see, this is another bad case of undefined behaivor for destruction of global objects.

EDIT: Loki Factory-Singleton throws "dead reference detected" in try-catch-block on ARM , the macro LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT could be relevant, since I would guess that triggers the destrcution, maybe without this the object will not get in the list of objects destroyed in atexit but still, my knowledge about Loki libraries is not good enough. Maybe you need to define a policy of lifetime of the singleton or something like that.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top