【问题标题】:C++ Exception to Exception-lessC++ 异常到无异常
【发布时间】:2021-12-05 01:53:52
【问题描述】:

我希望将一些大量使用异常的 C++ 代码编译到 wasm 目标中。不幸的是,大多数浏览器都没有打开 Webassembly 异常处理(我相信只有 Chrome 在标志 chrome://flags#enable-webassembly 后面支持它),并且在 emscripten 如何将异常包装到 javascript try/catch 中存在巨大的性能损失。我们注意到,当标志打开或关闭时,性能会下降 2 倍。

我相信对此的简短回答是“否”,但我想知道是否有已知的方法可以将带有异常的 C++ 代码转换为完全不使用异常的 C++ 代码(即使在父级中也不行) wrapper) 无需手动翻译。

【问题讨论】:

  • “无需手动翻译”是否意味着无需编辑代码?您是在问如何在不更改代码的情况下更快地编写代码?
  • @DrewDormann 不,如果有转译器或其他东西,我的意思更多,而不仅仅是“从头开始重写代码以不使用异常”。

标签: c++ google-chrome exception webassembly emscripten


【解决方案1】:

异常与返回值的唯一共同点是它是一种错误处理形式,就代码而言,它们完全是两个不同的东西。

除非您可以在 Boost 中禁用诸如 #define BOOST_NO_EXCEPTIONS 之类的异常的任何现有基础架构,并使用诸如 -fno-exceptions 之类的编译器标志禁用异常支持(这也将使 std 几乎无法使用) ..唯一的办法就是手动编辑...不过,有可能返回一个错误对象,或者抛出它,这样可以更容易逐步引入返回值。

【讨论】:

    【解决方案2】:

    UseNoexceptFalse:

    使用 UseNoexceptFalse 选项设置为 false。 默认启用,当你禁用它时,它会将 throw 替换为 noexcept

    示例:

    void foo() throw(int) {}
    
    struct bar {
      void foobar() throw(int);
      void operator delete(void *ptr) throw(int);
      void operator delete[](void *ptr) throw(int);
      ~bar() throw(int);
    }
    

    转换示例:

    void foo() {}
    
    struct bar {
      void foobar();
      void operator delete(void *ptr) noexcept(false);
      void operator delete[](void *ptr) noexcept(false);
      ~bar() noexcept(false);
    }
    

    进一步说明: modernize-use-noexcept

    【讨论】:

    • 这与问题无关。
    【解决方案3】:

    我认为浏览器中的异常会随着时间的推移而优化。我还认为异常必须 (RFC 2119) 不能用于计算的基础,而只能用于不应该 (RFC 2119) 发生的事件。

    显然“应该”是相对的并且因人而异(项目与项目),但磁盘错误显然是不应该发生的事件(除非您的程序使用损坏的磁盘和磁盘错误是正常事件)。当性能成为问题时,更改代码似乎是最好的解决方案。

    自动翻译听起来更好,但是当我想到标准的变化频率是 11、17、20... 我认为这样的翻译系统不会跟上,因为它的用例不会这么多(个人意见),可能不值得一开始就开发它。

    无论如何,一个快速的解决方案是将每个导出的函数包装在一个新的易于捕获的函数中,该函数捕获异常并将它们转换为返回值(或将此信息存储到线程局部变量中),与正常返回区分开来价值,如果有的话。这样至少异常不会传播到 JS 端。

    【讨论】:

    • 太棒了,你能链接到 RFC 吗?这样更容易参考吗?
    • 完成。该 RFC 来自我最喜欢的。
    • 知道了,还有关于您为什么(或何时)认为浏览器异常会被优化的任何说明?现在,它目前的性能提高了 2 倍。
    • “为什么”很简单。因为例外是相对较新的,并且尚未标准化:webassembly.org/roadmapgithub.com/WebAssembly/proposals。 “何时”是一个很难的问题。 Firefox 支持 WebAssembly sins v52 (mozilla.org/en-US/firefox/52.0/releasenotes),它和 JS 之间的调用在大约一年半后的某个地方变得很快 (hacks.mozilla.org/2018/10/…)。所以我想,如果这种趋势继续下去,一年半之后,那就是 2023 年。但它不可能确定。
    • OP 没有提供任何信息显示异常处理的大量开销被滥用为“计算基础”的结果。而且您以典型的方式滥用了 RFC 2119 中的动词。这些动词应该用于在规范的某些规范规则中强制或建议要求。您应该在相关规范中显示具体的参考资料,以使读者相信您的陈述是真实的,而不仅仅是遵循建议的“我认为”。但是,AFAIK,在语言和实现的规范规范上没有这样的规则。
    【解决方案4】:

    好吧,在您的代码中,您可以更改 every 函数以在它抛出异常时返回 std::variant<OkResult, ERROR>,但使用几乎所有第三方库(包括 STL)将是不可能或痛苦的。

    【讨论】:

      猜你喜欢
      • 2012-06-17
      • 1970-01-01
      • 2012-10-22
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多