Я пытаюсь использовать 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
от Локи в интернете.
Как решить проблему?
Так как я всегда хотел посмотреть на библиотеки 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 недостаточно хороши. Может быть, вам нужно определить политику жизни синглтона или что-то в этом роде.
Проблема в управлении временем жизни. Я сообщаю решение здесь для справки:
#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;
}