无法从 main.cpp 中的共享库中捕获异常
Posted
技术标签:
【中文标题】无法从 main.cpp 中的共享库中捕获异常【英文标题】:Cannot catch exception from shared library in main.cpp 【发布时间】:2014-05-04 17:09:12 【问题描述】:我目前正在开发一款基于插件架构的游戏。可执行文件主要由一个共享库加载器和几个接口定义组成。所有有趣的事情都发生在启动时加载的动态共享库中。
其中一个库类在某些情况下会引发异常。我希望能够捕捉到这个异常并用它做有用的事情,但这就是它变得奇怪的地方。请参阅以下简化示例代码:
main.cpp
int main()
try
Application app;
app.loadPlugin();
app.doStuffWithPlugin();
return 0;
catch(const std::exception& ex)
// Log exception
return 1;
Application.cpp
...
void doStuffWithPlugin()
plugin.doStuff();
...
插件.cpp
...
void doStuff()
throw exception_derived_from_runtime_error("Something is wrong");
...
Plugin.cpp 存在于动态共享库中,该库已成功加载并随后创建了类 Plugin 的对象。 exception_derived_from_runtime_error 在应用程序中定义。没有throw()
或noexcept
。
我希望在 main 中捕获 exception_derived_from_runtime_error,但这不会发生。使用 C++11 使用 GCC 4.8 编译,应用程序崩溃并显示 This application has requested the Runtime to terminate it in an unusual way.
。
我用catch(...)
替换了catch(const std::exception& ex)
,但这没有任何区别。奇怪的是,如果我在 doStuffWithPlugin() 中捕捉到异常,它就会起作用。如果我使用throw;
重新抛出它,它会再次失败,但如果我使用throw ex;
,它可能会被捕获:
Application.cpp
void doStuffWithPlugin()
try
plugin.doStuff();
catch(const exception_derived_from_runtime_error& ex)
// throw; <- Not caught in main().
// throw ex; <- Caught in main().
希望有人有想法。感谢您提供的所有帮助。
【问题讨论】:
你是如何在运行时加载库的? 只需在 Windows 上使用::LoadLibraryA
,在 Linux 上使用 ::dlopen
。两者都完美地工作。加载后,我选择了一个指向某些 getPlugin()
函数(这是库 ABI)的函数指针,该函数创建了插件对象。我应该提一下,每种方法都可以正常工作。只有抛出异常会导致奇怪的行为。
您是否确认确实从 C++ 代码中抛出了 exception_derived_from_runtime_error
?我问,因为 Windows 中的运行时异常不是 C++ 异常(它是 SE 异常)。捕获运行时异常需要开启 SE 处理(这可以在 Visual Studio 中完成,不知道 gcc)。
如果不是exception_derived_from_runtime_error
,doStuffWithPlugin() 中的捕获不应该失败吗? “SE 异常”是什么意思?
@tea2code SE(结构化异常)msdn.microsoft.com/en-us/library/windows/desktop/… 例如,访问冲突不是 C++ 异常。为了让 C++ 代码能够捕获这些异常,需要对代码进行调整。正如我的评论所提到的,对于 Visual Studio,这只是在编译时翻转设置的问题。我不知道 gcc 的步骤是什么。
【参考方案1】:
正如 cmets 中提到的,这似乎是 Windows 上共享库的问题。如果卸载库并且在此库中创建的对象保留在内存中,则会发生此行为。该应用程序似乎立即崩溃。如果使用 gcc 作为交叉编译器或 MinGW,则可以找到对这个问题的唯一参考。另见https://www.sourceware.org/ml/crossgcc/2005-01/msg00022.html
【讨论】:
以上是关于无法从 main.cpp 中的共享库中捕获异常的主要内容,如果未能解决你的问题,请参考以下文章