困惑于std :: runtime_error与std :: logic_error

我最近看到,如果命令行input是无法parsing的,那么boost program_options库会抛出一个logic_error 。 这挑战了我关于logic_errorruntime_error假设。

我认为逻辑错误( logic_error及其派生类)是内部失败导致的问题,通常以内部API的非法参数的forms遵守程序不variables。 从这个意义上说,它们大体上等同于ASSERT,但意味着在已发布的代码中使用(与ASSERT不同,它们通常不会编译成已发布的代码)。在将不同软件组件集成到debugging/testing版本中的情况下或者失败的后果是使得向用户提供关于无效不变条件的运行时反馈是重要的。

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

然而,program_options显然是很重要的(主要是?)作为parsing最终用户input的手段,所以在我的思维模型下,它肯定会在input错误的情况下抛出一个runtime_error

我哪里错了? 你是否赞同exceptioninput的提升模式?

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

类logic_error定义抛出的对象的types,作为exception来报告程序执行之前可能检测到的错误,例如违反逻辑先决条件或类不变式。

无法parsing的命令行参数似乎不适合。

相反,它将runtime_error描述为:

类runtime_error定义了作为exception抛出的对象的types,用于报告大概只有在程序执行时才能检测到的错误。

这似乎是一个更好的契合。

从纯粹的标准angular度来看,你是对的。 程序选项应根据错误是运行时还是逻辑来抛出派生自runtime_errorlogic_error类。 (我没有审查当前的代码,以确定这种想法分类目前的例外情况)。

从实际的angular度来看,我还没有看到C ++代码根据exception是logic_error还是runtime_error做出有用的决定。 毕竟,抛出一个logic_error而不是让assert文件的唯一原因是你想以某种方式尝试恢复,这与从运行时错误中恢复没有什么不同。 就我个人而言,我查看logic_errorruntime_error的方式与在Java中检查exception的方式相同 – 理论上很好,但在实践中没有用。 这意味着,也许,我只会使program_options::errorexception派生。 也就是说,当我发现每个人都在谈论“空闲时间”的时候。

目前的C ++ 0x标准草案(第19.2条)规定:

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

2)逻辑错误的显着特点是它们是由程序内部逻辑错误造成的。 从理论上讲,它们是可以预防的。

3)相反,运行时错误是由于超出程序范围的事件造成的。 他们不能容易地提前预测。

这与其他答案中引用的引号一起解释了为什么Boost.ProgramOptions抛出一个std :: logic_error,因为在程序执行之前大概可检测到的错误是由可预测的错误引起的。

用户可以validation文件是否存在,运行程序,并突然发现文件已被删除。 这就是为什么一个I / O问题总是一个runtime_error 。 有状态的问题是runtime_errors,即使调用者可以检查,因为另一个线程可能会导致问题。

logic_error是函数参数错误的时候。 只有那些本来可以用较强的types检查才能发现的东西。

所以,“丢失的文件”是一个runtime_error ,但“格式不正确的文件名”是一个logic_error

从技术上讲,函数中的逻辑错误也是一个逻辑错误,但是如果你足够聪明,可以在自己的函数中进行testing,那么你应该足够聪明,以防止它首先出现。

IMO,

  • std::logic_error是由用户C ++程序逻辑故意抛出的。 由用户程序预测。

  • std::runtime_error是由C ++ 运行时 (或者是语言的核心部分)引发的,以抽象出更低级别的错误。 只要没有任何用户代码涉及的意图发生。