【问题标题】:Does the ABI persist any more error information than an HRESULT?ABI 是否保留比 HRESULT 更多的错误信息?
【发布时间】:2019-09-14 23:04:14
【问题描述】:

在将常规 C++ 类移植到 Windows 运行时类时,我遇到了相当大的障碍。我的 C++ 类通过抛出自定义错误对象来报告某些错误情况。这允许客户端方便地过滤异常,记录在公共界面中。

我似乎找不到一种可靠的方法来通过 ABI 传递足够的信息以使用 Windows 运行时复制相同的保真度1。假设HRESULT 是唯一的通用错误报告信息,我评估了以下选项:

  1. “显而易见”的选择:将异常条件映射到任何预定义的HRESULT values。虽然这在技术上可行(推测),但调用站点无法区分源自实现的错误和源自实现的被调用者的错误。
  2. 发明自定义HRESULTs。如果this layout 仍然适用于 Windows 运行时,我可以轻松设置 Customer 位并疯狂地使用 my 27 位的错误代码表示。这有效,直到其他人也这样做。我不知道有任何方法可以将 HRESULT 归因于接口,这可以解决这种歧义。
  3. 即使上述任何一项都可以按预期工作,按照规定抛出hresult_errors,调用站点仍将受语言投影的支配。虽然 C# 似乎允许跨 ABI 传递任何 System.Exception(-derived) 错误对象,并在调用站点重新抛出它们,但 C++/WinRT 仅支持大约 14 种不同的异常类型(请参阅 throw_hresult)。李>

这些选项都不允许通过 ABI 获得足够完整的错误信息,看来HRESULT 可能还不够。 Windows 运行时是否有任何配置以允许其他(任意)错误信息通过 ABI?


1我对传递实际的 C++ 异常并不十分感兴趣。相反,我正在寻找一种方法,让客户能够以自然的方式唯一识别记录在案的错误情况。传递自定义 Windows 运行时错误类型会很好。

【问题讨论】:

  • 听起来RoOriginateError 就是您要找的。您可以为您的错误存储一个自定义字符串,收到错误 hresult 的调用者可以通过GetRestrictedErrorInfo 调用检索它。这就是异常文本在 C# 中的显示方式,即使从 C++/CX 抛出异常也是如此。

标签: error-handling windows-runtime c++-winrt


【解决方案1】:

这里有几个选项。对于具有明确定义的预期故障模式的 Windows 运行时 API,我们的一般 API 指南是故障信息应该是正常参数和返回值的一部分。在这种情况下,我们通常会创建一个 TryDoSomething API,并通过 return 或 out 参数提供扩展的错误信息。这对我们来说最有效,因为没有一致的方法来映射所有语言的异常。这是我们希望将来在xlang 中重新讨论的话题。

HRESULT 可以使用,但需要注意。 HRESULT 值在除 C++ 之外的任何东西中都可能令人讨厌,您需要在本地重新定义它们,因为您不能只使用标头。它们会在大多数语言中生成异常,因此如果这很常见,您将为组件的客户端创建调试器噪音。

最后一个选项允许您将存储在 COM 对象中的特定于语言的异常跨 ABI 边界(以及向上的 COM 逻辑堆栈,包括跨编组调用)传输。实际上,它只能由使用与组件本身相同的编译器、设置和类型定义编译的 C++ 代码使用。例如。将它从使用 VC 编译的组件传递到使用 Clang 编译的组件可能会导致内存损坏。

假设我没有吓跑你,你会想看看RoOriginateLanguageException。它允许您将异常包装在 COM 对象中,并将其与其他 winrt 错误数据一起存储在 TLS 中。我们在投影中使用它来使回调中引发的异常能够以受控方式传播到使用相同投影的外部代码,该方式可以安全地通过可能使用其他语言或工具编写的其他代码展开。这就是对 C# 和其他语言的支持的实现方式。

谢谢,

【讨论】:

  • 阅读此答案后我意识到,我在描述我的要求时不够具体。我假设您在最后一个选项中指的是存储在 COM 对象中的 std::exception_ptr 对象。这完全抵消了我们从建立 ABI 中获得的大部分好处,而这并不是我想要的。有趣的是,显然我们可以让 COM 异常对象通过 ABI(除了HRESULT)。所以理论上我们可以在呼叫站点有throw MyWinRTEx{};catch(MyWinRTEx const&)(前提是我们有语言投影支持)。
  • 这在实践中真的可能吗,还是我忽略了一些东西?如果这确实可行,是否正在为未来的 C++/WinRT 投影进行评估?
  • WinRT 今天还没有办法做到这一点,但没有理由不能做到这一点。这就是我想在 xlang 项目(同时具有 WinRT 和 xlang 工具)中重新审视的内容。这有点复杂,因为并非所有语言都支持异常对象作为其自然错误处理路径,但基本要点是,如果您使用这种语言,为什么不处理自然异常类型?
  • 当您说 "WinRT" 时,您指的是 Windows 运行时,还是 C++/WinRT 语言投影?当您提到 xlang 项目时,这是否意味着更改最终也会使其成为 C++/WinRT?
  • 我指的是 Windows 运行时类型系统和操作系统支持。对预计异常的支持不太可能回到 WinRT。这不是不可能,但不太可能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-03
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多