我最近看到如果命令行输入不可解析,boost program_options库会抛出logic_error
。这挑战了我对logic_error
与runtime_error
的假设。
我认为逻辑错误(logic_error
及其派生类)是由于内部无法遵守程序不变量而导致的问题,通常是以内部API的非法参数形式出现的。从这个意义上讲,它们大部分相当于ASSERT,但意味着在已发布的代码中使用(与ASSERT不同,它通常不会编译成已发布的代码。)它们在调试/测试版本中集成单独的软件组件是不可行的情况下非常有用。或者失败的后果是,向用户提供关于无效不变条件的运行时反馈非常重要。
同样,我认为runtime_error
仅由程序员控制之外的运行时条件产生:I / O错误,无效的用户输入等。
但是,program_options显然(主要是?)用作解析最终用户输入的一种方法,所以在我的心智模型中,它确实应该在输入错误的情况下抛出runtime_error
。
我哪里错了?你是否同意异常打字的提升模型?
答案 0 :(得分:31)
在这种情况下,我认为(至少在大多数情况下)你是对的,这是错误的。该标准将logic_error
描述为:
类logic_error定义了作为异常引发的对象类型,以报告在程序执行之前可能检测到的错误,例如违反逻辑前置条件或类不变量。
无法解析的命令行参数似乎不太适合。
相比之下,它将runtime_error
描述为:
类runtime_error定义了作为异常引发的对象类型,以报告仅在程序执行时可能检测到的错误。
这似乎更适合。
答案 1 :(得分:8)
从纯粹的标准角度来看,你是对的。 program_options应该抛出从runtime_error
或logic_error
派生的类,具体取决于错误是运行时还是逻辑错误。 (我没有检查当前的代码来确定当前异常的这种想法分类。)
从实际角度来看,我还没有看到C ++代码根据异常是logic_error
还是runtime_error
做出有用的决策。毕竟,抛出logic_error
而不是让断言文件的唯一原因是,如果你想以某种方式尝试恢复,那与恢复运行时错误没有什么不同。就个人而言,我以与Java中检查异常相同的方式查看logic_error
与runtime_error
- 理论上很好,但在实践中没有用处。这意味着,我可能会program_options::error
从exception
派生出来。也就是说,当我发现'业余时间'时,每个人都在谈论。
答案 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,
std::logic_error
。由用户程序预测。
std::runtime_error
由C ++ 运行时(或语言的核心部分......)引发,以抽象低级错误。如果不涉及任何用户代码,就会毫无意图地发生。