【问题标题】:c++ exceptions, can what() be NULL?c++ 异常,what() 可以为 NULL 吗?
【发布时间】:2009-06-24 13:46:32
【问题描述】:

捕获的 std::exception 是否可以让 what() 为 NULL?

检查 e.what() 是否低于开销?

//...
}
catch (const std::exception& e)
{
  std::string error;
  if(e.what())
    error = e.what();
}

【问题讨论】:

    标签: c++ exception


    【解决方案1】:

    字符串的内容是实现定义的,所以我猜答案是肯定的。

    编辑:保护它。标准说:

    virtual const char* what() const throw();
    5 Returns: An implementation-defined NTBS.
    

    所以它必须返回一个字符串,而不仅仅是一个指针。并且字符串不能是NULL。正如其他人所指出的,很容易推导出 what() 确实返回 NULL 的异常,但我不确定这些事情如何符合标准一致性。当然,如果您在自己的异常类中实现 what(),我会认为允许它返回 NULL 是非常糟糕的做法。

    更多:

    有关what() 是否可以返回 NULL 的进一步问题以及类似的令人兴奋的问题,请参阅Extending the C++ Standard Library by inheritance?

    【讨论】:

    • 但是如果你覆盖了什么并且它被 const std::exception& 捕获,那么它可能是 NULL,所以最好检查一下吗?
    • @j_random_hacker,如果选择返回为 std::string 与 const char*,他们可以在这种情况下。这将在强级别强制执行至少一个有效的空字符串。但为时已晚:(。
    • @JaredPar 返回字符串涉及内存分配,如果您试图报告内存分配失败,这可能是不可取的。
    • @Net Citizen - 我实际上会对系统中的所有异常类进行代码审查,并确保它们不返回 NULL。在给定的系统中可能没有那么多代码,您可以通过预先做一些工作来节省大量多余的代码。
    • 关键是要有正确的继承,必须保留基类承诺。因此,如果基类函数承诺永远不会返回 NULL(这里似乎就是这种情况),那么任何派生类都必须承诺相同,否则继承不正确(损坏)。
    【解决方案2】:

    如果有人从 std::exception 继承并重写了返回 NULL 的内容,那么这是可能的。

       class CMyException : public std::exception
       {
       ...
           virtual const char * what () const {return NULL;}
       };
    

    尽管 Neil 在标准中找到了出色的发现,但检查 NULL 可能仍然很好。尽管 std::exception 的哪些子类的规范表明它们不应返回 NULL,但编译器中的任何内容都不会强制执行此操作,并且根据语言,上述代码仍然是合法的。

    这可能是使用断言的理想情况...

     assert(except.what() != NULL);
    

     if (except.what() != NULL)
     {
          ... normal processing ...
     }
     else
     {
          assert(false);
     }
    

    因为在这种情况下,某些事情可能永远不会发生,并且您假设它不应该发生,但仍然想知道(在调试模式下)您的假设何时被证明是错误的。然后您可以解决您的错误假设或解决可能与您的假设相反的错误代码(确保 what() 不返回 NULL)。

    【讨论】:

    • 有可能在语言中(即您的代码将编译),但这在 C++ 标准中是不合法的——请参阅 Neil 的回答。
    • 是的,如果您只返回 NULL,我不确定这是否不是未定义的行为。它违反了它为 what() 指定的内容。
    【解决方案3】:

    当然可以是NULL:

    class myexception: public exception
    {
      virtual const char* what() const throw()
      {
        return NULL;
      }
    } myex;
    

    【讨论】:

    • 可以在语言中执行此操作(即您的代码将编译),但 C++ 标准禁止这样做——请参阅 Neil 的回答。 IOW,不要这样做,因为其他人的代码可能依赖于你不这样做。
    • 我不认为它是“非法的”——标准规定了 std::exception::what 的行为——它似乎没有对从 std:: 派生的用户分类提出任何要求例外。
    【解决方案4】:

    正如许多其他人指出的那样,what() 不应该返回一个空指针,但它可能。空测试的运行时开销仅在可能不太重要的例外情况下发生。

    无论如何,我建议至少使用assert

    如果代码空间也是一个问题,希望assert、您的测试、代码审查和其他 QA 将足够完整,以便在您发布之前追踪任何违规、不合规的异常。

    此外,请注意自身可能抛出的异常处理代码(例如,正如其他人所指出的,在处理 std::bad_alloc 异常时使用 std::string 分配内存。)

    【讨论】:

    • 在处理 std::bad_alloc 时分配内存不是一个好主意。对于其他例外情况,不使用 std::string 是没有意义的。
    猜你喜欢
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多