如何将C++异常重新抛出为.NET异常并保留消息、堆栈跟踪和原始异常?

3

我有一个C++/CLI的“包装库”,用于与一个未经管理的第三方库通信,以使该功能在我的.NET项目中可用。一些未经管理的库函数会抛出继承自std::exception的异常。我希望在.NET空间中将它们重新抛出为有意义的异常。

目前,我对每个未经管理的调用都这样做:

try {
    myThirdPartyObject -> doUnmanagedStuff();
} catch(std::exception e) {
    throw gcnew InvalidOperationException(gcnew String(e.what()));
}

然而,这种方法既没有保留调用栈,也没有保留原始异常。如果我只是让异常继续抛出,我只能得到一个带有消息“An external component has thrown an exception”的SEHException异常。

这种情况是否可能发生?如果是,应该如何处理?


有点偏题,但你应该通过引用捕获 C++ 异常 (catch (std::exception& e))。 - Stephan
为了避免切片,使用“const”引用会更好(catch (const std::exception& e))。 - Sebacote
@SébastienCôté:为什么捕获const引用更好?您永远不会在catch块中得到const异常。并且在重新抛出之前,您无法调用任何非const函数或修改异常。 - Stephan
请参考以下链接: "https://dev59.com/PnI95IYBdhLWcg3wzRXv" 和 "https://dev59.com/-Gsz5IYBdhLWcg3w6MJS" - Sebacote
在本地的 C++ 程序中,你也不会得到堆栈跟踪或其他任何东西,只有 exception::what()。当你重新抛出它时,这并不会神奇地变得更好。 - Hans Passant
1个回答

2
我认为这是不可行的。与托管代码不同,标准C++没有由运行时引擎支持的自动处理机制。虽然有捕获堆栈跟踪的方法,但它们是特定于平台的(请参见Windows方式此处);无论如何,在抛出异常之前应该捕获并附加堆栈信息到异常对象中,而在你的情况下,这不是一个选择,因为你正在调用我假设你不能修改的第三方库。

"Sentient运行时引擎" - crashmstr
CLR的过分严谨表达式 :) - Sebacote

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接