对std :: runtime_error和std :: logic_error感到困惑

时间:2010-05-27 19:03:29

标签: c++ boost stl exception

我最近看到如果命令行输入不可解析,boost program_options库会抛出logic_error。这挑战了我对logic_errorruntime_error的假设。

我认为逻辑错误(logic_error及其派生类)是由于内部无法遵守程序不变量而导致的问题,通常是以内部API的非法参数形式出现的。从这个意义上讲,它们大部分相当于ASSERT,但意味着在已发布的代码中使用(与ASSERT不同,它通常不会编译成已发布的代码。)它们在调试/测试版本中集成单独的软件组件是不可行的情况下非常有用。或者失败的后果是,向用户提供关于无效不变条件的运行时反馈非常重要。

同样,我认为runtime_error仅由程序员控制之外的运行时条件产生:I / O错误,无效的用户输入等。

但是,program_options显然(主要是?)用作解析最终用户输入的一种方法,所以在我的心智模型中,它确实应该在输入错误的情况下抛出runtime_error

我哪里错了?你是否同意异常打字的提升模型?

5 个答案:

答案 0 :(得分:31)

在这种情况下,我认为(至少在大多数情况下)你是对的,这是错误的。该标准将logic_error描述为:

  

类logic_error定义了作为异常引发的对象类型,以报告在程序执行之前可能检测到的错误,例如违反逻辑前置条件或类不变量。

无法解析的命令行参数似乎不太适合。

相比之下,它将runtime_error描述为:

  

类runtime_error定义了作为异常引发的对象类型,以报告仅在程序执行时可能检测到的错误。

这似乎更适合。

答案 1 :(得分:8)

从纯粹的标准角度来看,你是对的。 program_options应该抛出从runtime_errorlogic_error派生的类,具体取决于错误是运行时还是逻辑错误。 (我没有检查当前的代码来确定当前异常的这种想法分类。)

从实际角度来看,我还没有看到C ++代码根据异常是logic_error还是runtime_error做出有用的决策。毕竟,抛出logic_error而不是让断言文件的唯一原因是,如果你想以某种方式尝试恢复,那与恢复运行时错误没有什么不同。就个人而言,我以与Java中检查异常相同的方式查看logic_errorruntime_error - 理论上很好,但在实践中没有用处。这意味着,我可能会program_options::errorexception派生出来。也就是说,当我发现'业余时间'时,每个人都在谈论。

答案 2 :(得分:5)

C ++ 0x Standard的当前草案(第19.2条):

  

1)在反映的错误模型中   这些类(即异常类型),错误分为   两大类:逻辑错误和   运行时错误。

     

2)区别特征   逻辑错误是他们应得的   对内部逻辑的错误   程序。从理论上讲,他们是   预防的。

     

3)相比之下,运行时错误到期了   超出范围的事件   程序。他们不容易   提前预测。

与其他一个答案中引用的引号一起,这解释了为什么Boost.ProgramOptions会抛出一个std :: logic_error,以防止由程序执行前可能检测到的错误引起的可预防错误。

答案 3 :(得分:1)

用户可以验证文件是否存在,运行程序,然后突然得知该文件已被删除。这就是I / O问题总是runtime_error的原因。状态问题是runtime_errors,即使调用者可能已经检查过,因为另一个线程可能会导致问题。

logic_error是函数的参数错误的时候。对于那些早期可以通过更强类型检查捕获的东西,它只是

因此,“遗失文件”是runtime_error,但“格式不正确的文件名”是logic_error

从技术上讲,函数中的逻辑错误也是logic_error,但如果你足够聪明,可以在自己的函数中测试它,那么你应该足够聪明以防止它首先。

答案 4 :(得分:0)

IMO,

    用户C ++程序 logic 有意抛出
  • std::logic_error。由用户程序预测。

  • std::runtime_error由C ++ 运行时(或语言的核心部分......)引发,以抽象低级错误。如果不涉及任何用户代码,就会毫无意图地发生。