Loki::Factory 在程序退出时抛出异常

Posted

技术标签:

【中文标题】Loki::Factory 在程序退出时抛出异常【英文标题】:Loki::Factory throwing an exception on program exit 【发布时间】:2013-09-05 06:04:10 【问题描述】:

我正在尝试在使用 VC8 编译的项目中使用 Loki::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;

一切都很好,直到系统暂停要求使用按键(如system("pause"));但是,当我按下该键时,由于从函数内部抛出未处理的异常,程序中止

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

可以在 Visual Studio 文件“memory”中找到。异常是访问冲突,堆栈开始于:

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

我在 Internet 上找不到 Loki 使用 std::auto_ptr 的任何参考。

如何解决问题?

【问题讨论】:

您是否在调试器中看到调用堆栈,在调用~auto_ptr 的位置?抛出哪个异常? 尝试将虚拟析构函数添加到基类。 @user1837009 添加虚拟析构函数没有帮助。你当然是对的,应该是这样。我只是没有在示例中将其设为虚拟 【参考方案1】:

因为我一直想看看 Loki 库,所以我利用了这个机会。好吧,首先,这个问题与 MSVC 版本无关,我确实在 VS2008 上运行了相同的示例,并且使用 VS2008 构建的 Loki 库得到了相同的结果。第二:

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

这很好用。我在您的示例中检查了崩溃,似乎工厂正在删除关联容器,您创建的仿函数应该在它已经被销毁之后所在的位置。在我看来,这是因为 Loki 正在连接 atexit() 并在那里删除一些东西(不知道为什么,我猜是为了处理 Singleton 对象),这就是你的 Functor 被删除的地方,然后在你工厂的析构函数之后调用,然后对关联容器的erase 调用失败。好吧 - 如果不是什么大不了的事,不要让工厂成为全局对象。如果这很重要,请尝试调试并找出 Loki 为何会像在 atexit 中所做的那样,也许您需要进行更多设置。但至少在我看来,这是另一个破坏全局对象的未定义行为的坏情况。

编辑:Loki Factory-Singleton throws "dead reference detected" in try-catch-block on ARM ,宏 LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT 可能是相关的,因为我猜这会触发破坏,也许没有这个,对象将不会进入 atexit 中破坏的对象列表中,但我仍然了解 Loki图书馆还不够好。也许您需要定义单例的生命周期策略或类似的东西。

【讨论】:

已经尝试过 LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT,没有任何作用 是的,我尝试使用该宏重建所有 Loki 解决方案,但不好,即使 README 声明 Define LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT to avoid static instantiation/delete order problems 在问题中发布了解决方案。你基本上是对的! 是的,我一路上看到了 SingletonHolder 模板,但由于我对 Loki 缺乏了解,所以没有深入了解。没有它它仍然很奇怪。【参考方案2】:

问题在于生命周期管理。我在这里报告解决方案以供参考:

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

【讨论】:

以上是关于Loki::Factory 在程序退出时抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

java写的excel导出时抛出的异常

Java 异常 重写方法时抛出异常

搭建控制器时抛出的调用目标抛出异常

如何防止后台线程抛出的异常让程序崩溃退出

Gradle 在从网络下载工件时抛出错误.. 异常:Gradle 任务 assembleDebug 失败,退出代码为 1

在继承中重写方法时抛出异常的问题