Loki :: Factory создает исключение при выходе из программы

Я пытаюсь использовать Loki::Factory в проекте, который скомпилирован с VC8 (мне не разрешено переключаться на более новый компилятор). У меня возникла проблема при выходе из программы, которую я могу воспроизвести с помощью этого базового кода (это самое малое, чего вы могли бы достичь при использовании фабрики)

#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;
}

все в порядке, когда система доходит до паузы, требующей использования для нажатия клавиши (как для system("pause")); однако, когда я нажимаю клавишу, программа прерывает работу из-за необработанного исключения, вызванного функцией

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

который можно найти в файле визуальной студии «Память». Исключением является нарушение прав доступа, и стек начинается с:

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++

Я не мог найти никаких ссылок на использование std::auto_ptr от Локи в интернете.

Как решить проблему?

0

Решение

Так как я всегда хотел посмотреть на библиотеки Loki, я использовал этот шанс. Ну, для начала, проблема не связана с версиями MSVC, я запустил один и тот же пример на VS2008 и библиотеки Loki, построенные на VS2008, и получили те же результаты. Во-вторых:

#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;
}

Это отлично работает. Я рассмотрел сбой на вашем примере и, похоже, что Factory удаляет контейнер ассоциации, в котором, как предполагается, созданный вами функтор должен находиться после его уничтожения. Сдается мне, что это потому, что Локи подключается atexit() и удалив некоторые вещи там (не уверен, почему, я думаю, для обработки объектов Singleton), именно здесь ваш Functor удаляется, а затем после вызова деструктора вашей фабрики и затем erase вызов на контейнере ассоциации не удается. Что ж, если это не так уж важно, не превращайте фабрику в глобальный объект. Если это огромная сделка, попробуйте отладить и выяснить, почему Локи делает то, что делает в atexit, может быть, вам нужно настроить что-то еще. Но, по крайней мере, насколько я вижу, это еще один плохой случай неопределенного поведения для уничтожения глобальных объектов.

РЕДАКТИРОВАТЬ: Локи Фабрика-Синглтон броски "обнаружена мертвая ссылка" в блоке try-catch на ARM , макрос LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT может быть релевантным, так как я предполагаю, что это вызывает разрушение, возможно, без этого объект не попадет в список объектов, уничтоженных в atexit но, тем не менее, мои знания о библиотеках Loki недостаточно хороши. Может быть, вам нужно определить политику жизни синглтона или что-то в этом роде.

1

Другие решения

Проблема в управлении временем жизни. Я сообщаю решение здесь для справки:

#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;
}
0

По вопросам рекламы [email protected]