【问题标题】:how to check failure of constructor with exception disabled如何在禁用异常的情况下检查构造函数的失败
【发布时间】:2017-03-25 12:04:34
【问题描述】:

在我们的代码库中,我们不使用 c++ 异常,即 gcc 编译选项中的“-fno-exceptions”(请注意这是我们公司的政策,因此无需争论)。但是,在这种情况下,如何检查标准库中抛出异常的构造函数是否失败。我已经阅读了一些 SO 帖子,但仍然没有明确的想法。例如,在 c++11 中,std::regex("pattern") 可以抛出一个 regex_error 异常。如果我有以下代码:

class Wrapper {
public:
    bool create(std::string pattern) {
      try {
        m_regex = std::regex(pattern);
        m_state = true;
      } catch (std::regex_error& e) {
        //handle error case
        m_state = false;
      }
    }
private:
    std::regex m_regex;
    bool m_state;
}

注意: m_regex = std::regex(pattern);

会打电话

explicit basic_regex(const CharT* s, flag_type f = std::regex_constants::ECMAScript)

可以抛出异常并移动赋值运算符

basic_regex& operator=(basic_regex&& __rhs) noexcept

现在,如果没有使用异常的选项,我们如何检查 std::regex 的构造函数是否失败?

class Wrapper {
public:
    create(std::string pattern) {
        m_regex = std::regex(pattern);
        // now, how to check? 
        // if (m_regex)?
        m_state = true;
    }
private:
    std::regex m_regex;
}

我没有发现 std::regex 中有任何状态可以指示失败。

选项1:我可以假设如果正则表达式构造函数失败,会发生abort(),那么下面的语句m_state = true不会被执行?我检查了一下,似乎 abort() 通常在启用异常的情况下发生,但没有使用 catch。所以这是错误的。

选项 2:我可以使用std::regex* ptr_regex = new std::regex("pattern"),并检查 ptr_regex 的空性吗?

【问题讨论】:

  • 你不能。如果不允许使用异常(即使只是为了捕获),则必须避免使用 STL。
  • 正如@Gonmator 所说,除了它不仅仅是 STL:您必须避免使用 C++ 标准库的大多数部分,尤其是正则表达式。
  • “我们公司不允许例外”的一个很好的解决方案,除非这是出于非常好的原因,例如非常低资源的嵌入式编程,或者处理遗留代码库(这就是它的方式在谷歌),如果可能的话,是在别处找工作。因为,由于无能者制定了一项重要政策,其余政策很可能同样糟糕。这同样适用于例如首席执行官透露缺乏职业道德指南:这可能影响了几乎整个组织。
  • @Cheersandhth.-Alf,是的,不幸的是,它属于你提到的充分理由之一(实际上是两者)。我真的在互联网上搜索了一些工作,但到目前为止仍然一无所知。

标签: c++ c++11 exception constructor


【解决方案1】:

这是一个尚未解决的问题,one of the big open problems discussed by SG14,委员会的“低延迟”研究组。

就标准而言,这只是未定义的。例外不是可选的,如果你关闭它们会发生什么,也没有说明。因此,标准库通常不提供处理错误的替代方法。目前有一种趋势是在未来的提案中有所缓解。例如,当前的 Filesystem TS 具有非抛出重载,它们为所有可能抛出异常的函数返回错误代码。以类似的方式为现有标准库设施提供非抛出替代方案是可能的,但这正是 SG14 试图弄清楚的。

到目前为止,重要的问题是:你的编译器在禁用异常编译时遇到throw(或try/catch)会做什么?如前所述,标准根本没有规定这一点,因此这里的任何解决方案都必然是不可移植的。您可能无法通过throw 检测到库指示的错误或从错误中恢复,因此如果您无法事先排除会引发异常,您可能希望避免抛出函数(和因此,大多数标准库)。

希望这种情况在未来会有所改善。

【讨论】:

  • 是的,我们真的坚持这一点。但我们必须找到一些解决方案或变通,因为我们或我们的客户已经等不及委员会了。
  • @pepero 我感觉到你的痛苦。您可能希望密切关注替代实现。出于这个和其他原因,许多供应商已经提出了他们自己的标准库设施实现。 'Embedded STL' 是互联网搜索的一个很好的起始关键字。有时 Boost 提供带有额外保证的实现。不幸的是,我不知道std::regex 的任何实现可以解决您的问题。
【解决方案2】:

创建一个库,其目的是包装需要异常的std 实用程序。

这个库在启用异常的情况下编译的。

它要么存储 optional<std::regex> 的等价物(例如)。它提供了可能失败的构造函数(在库的.cpp 东西中)调用构造函数,然后尝试/捕获并将失败转换为空的regex

如果还有其他可以抛出的操作,它会将它们类似地包装在具有错误返回路径的方法中。也许他们会返回std::experimental::expected<T, error_information>

您必须小心 ODR 以及此库与使用禁用异常的 std 库编译的代码之间的链接,因为它们之间的内联函数会有所不同。我不知道如何避免这个问题的细节。在某些平台上,std 库函数可能是动态链接的,您可能会加载错误的函数以错误的方式编译。再说一次,我不知道如何解决这个问题。

根据我从一个非常快速的谷歌上可以看出,膨胀和一个启用异常的库应该主要限制为与该库的大小一起扩展。测试一下。

【讨论】:

    猜你喜欢
    • 2010-12-29
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    • 2017-08-04
    • 1970-01-01
    • 2015-10-19
    相关资源
    最近更新 更多