断言,异常,运行时错误或未定义的行为?

时间:2013-08-20 18:39:51

标签: c++ fsm design-by-contract

我正在使用这些公共方法处理有限状态机库:

template <typename STATE_T>
void add_state();              // allocate STATE_T on heap - STATE_T must derive from state

template <typename FROM_STATE_T, typename TO_STATE_T>
void link_state(std::function<bool()> cond, unsigned int priority);

// search for base state pointer that can be dynamically caste d to STATE_T* type, set this state as the beginning state
template <typename STATE_T>
void begin_state();

void execute();

//STATE_T must be a user defined state class that inherits from the base state class.

我在编译时选择了运行时实现,因为在为状态使用可变参数模板参数时,接口会更复杂。但是,我想强制执行一些限制,以确保程序员在实现状态机时不会引入错误。

以下是我要强制执行的约束:

  1. 无法添加重复状态(即添加两个相同的派生类型)
  2. 无法链接不存在的状态(例如状态类型不在fsm状态列表中)
  3. 各州必须有一个入境点/可以到达
  4. 必须存在开始和结束状态
  5. 执行不能同时运行多次
  6. 断言中止程序并明确遵守这些约束,但这是正确的选择吗?

    有可能违反了1,2,3并且fsm仍然处于有效状态(简单地什么都不做)但是我不喜欢暗中处理这些的想法,因为它通过隐藏引入了一种虚假的安全感程序员错误。

    如果我抛出1,2,3的异常并且程序员捕获它们,那么fsm仍然可以处于有效状态,允许运行不良的fsm。

    5是不应该做的事情。我应该处理这个问题,还是留下UB?

    用于这些约束的最合适的机制是什么?

1 个答案:

答案 0 :(得分:2)

这是处理错误的典型问题。答案通常取决于成本。这个问题被忽视的成本是多少?程序因异常而中止的成本是多少?

在大多数情况下,程序崩溃的成本并不是那么大。用户只需重新启动它。在这种情况下,你应该去处理未处理的异常。通过这种方式,您可以快速发现错误,修复它们,最终获得更好的程序。

有一种混合方法:在DEBUG构建中,使用“断言失败”消息框处理错误(通常使用ASSERT()宏完成),但在发布版本中,静默处理错误。但是,这会让问题在客户端计算机上不被注意,经常会触发其他很难找到的错误。

最后,你担心程序员可以处理异常:这不是你应该考虑的事情。你指出了一个致命的错误,如果程序员忽略它,那就是他的错。