Boost C++ 库

...世界上最受尊敬和设计最精良的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

PrevUpHomeNext

错误处理示例

请参阅 错误处理文档,详细了解错误处理机制,包括分布和函数的常见“错误”参数,以及如何使用 策略 来控制它。

但是,默认情况下,对于域错误、极点错误、数值溢出和内部评估错误,将引发异常。要避免抛出异常,而是获得适当的返回值,通常是 NaN(域错误、极点错误或内部错误),或无穷大(来自溢出),您需要更改策略。

以下示例演示了当遇到无效参数时设置宏 BOOST_MATH_DOMAIN_ERROR_POLICY 的效果。在本示例中,我们将传递一个负的自由度参数给学生 t 分布。

由于我们知道这是一个单文件程序,我们可以简单地添加

#define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error

到源文件顶部,将默认策略更改为在发生域错误时简单地返回 NaN 的策略。或者我们可以使用

#define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error

以确保在发生域错误时设置 ::errno,并返回 NaN。

如果程序由单个翻译单元组成 并且 我们将 define 放在任何 #includes 之前,这是安全的。 请注意,如果我们在 include 之后添加 define,它将不起作用! 诸如

warning C4005: 'BOOST_MATH_OVERFLOW_ERROR_POLICY' : macro redefinition

之类的警告是它不会产生预期效果的明确标志。

我们将从示例程序的必要 include 开始

   #define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error

// Boost
#include <boost/math/distributions/students_t.hpp>
   using boost::math::students_t;  // Probability of students_t(df, t).

// std
#include <iostream>
   using std::cout;
   using std::endl;

#include <stdexcept>


#include <cstddef>
   // using ::errno

接下来我们将定义程序的 main() 来调用具有无效自由度参数的学生 t 分布,该程序设置为处理异常或 NaN

int main()
{
   cout << "Example error handling using Student's t function. " << endl;
   cout << "BOOST_MATH_DOMAIN_ERROR_POLICY is set to: "
      << BOOST_MATH_STRINGIZE(BOOST_MATH_DOMAIN_ERROR_POLICY) << endl;

   double degrees_of_freedom = -1; // A bad argument!
   double t = 10;

   try
   {
      errno = 0; // Clear/reset.
      students_t dist(degrees_of_freedom); // exception is thrown here if enabled.
      double p = cdf(dist, t);
      // Test for error reported by other means:
      if((boost::math::isnan)(p))
      {
         cout << "cdf returned a NaN!" << endl;
         if (errno != 0)
         { // So errno has been set.
           cout << "errno is set to: " << errno << endl;
         }
      }
      else
         cout << "Probability of Student's t is " << p << endl;
   }
   catch(const std::exception& e)
   {
      std::cout <<
         "\n""Message from thrown exception was:\n   " << e.what() << std::endl;
   }
   return 0;
} // int main()

以下是在默认构建(抛出异常的构建)下程序输出的样子

Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: throw_on_error

Message from thrown exception was:
   Error in function boost::math::students_t_distribution<double>::students_t_distribution:
   Degrees of freedom argument is -1, but must be > 0 !

或者,让我们使用以下命令构建

#define BOOST_MATH_DOMAIN_ERROR_POLICY ignore_error

现在程序输出是

Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: ignore_error
cdf returned a NaN!

最后,让我们使用以下命令构建

#define BOOST_MATH_DOMAIN_ERROR_POLICY errno_on_error

这给出了输出 show errno

Example error handling using Student's t function.
BOOST_MATH_DOMAIN_ERROR_POLICY is set to: errno_on_error
cdf returned a NaN!
errno is set to: 33
[Caution] 注意

如果启用了异常抛出(默认),但您没有 try & catch 块,则程序将因未捕获的异常而终止,并可能中止。

因此,为了获得有用的错误消息的好处,建议大多数应用程序启用 所有异常并使用 try & catch

但是,为了简单起见,大多数示例都没有这样做。


PrevUpHomeNext