无法从 main.cpp 中的共享库中捕获异常

Posted

技术标签:

【中文标题】无法从 main.cpp 中的共享库中捕获异常【英文标题】:Cannot catch exception from shared library in main.cpp 【发布时间】:2014-05-04 17:09:12 【问题描述】:

我目前正在开发一款基于插件架构的游戏。可执行文件主要由一个共享库加载器和几个接口定义组成。所有有趣的事情都发生在启动时加载的动态共享库中。

其中一个库类在某些情况下会引发异常。我希望能够捕捉到这个异常并用它做有用的事情,但这就是它变得奇怪的地方。请参阅以下简化示例代码:

ma​​in.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 中的共享库中捕获异常的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C 在静态库中抛出异常。如何使用该库从程序中捕获异常?

如何从Publish-Module中捕获异常?

捕获 NSKeyedUnarchiver 异常

Java中的异常处理

无法将char转换为c#中类库中的项目

如何从线程中捕获异常