【发布时间】:2019-05-03 06:56:02
【问题描述】:
Herb Sutter 就 C++ 中异常的未来以及即将替换或增强现有 assert 的合同提交了 talk at ACUU Conference。
他假设以下规则来处理错误:
-
系统损坏(例如,堆栈溢出):终止
-
编程错误(例如违反前提条件):断言、合同
-
可恢复的错误(例如,网络故障):异常,错误代码
虽然我同意,但我没有使用这种方法,而是将 2 和 3 合二为一。我这样做是因为我不知道如何测试断言或即将到来的合同。两者都使用类似的机制,它们的违规会导致程序终止并在此之前调用可选的处理程序。
来自documentation(重点是我的):
可以使用两种违规继续模式之一来翻译程序:
- off(如果没有选择继续模式则默认):执行后 违规处理程序完成后,调用 std::terminate;
- on:违规处理程序执行完成后,执行 继续正常进行。
鼓励实现不提供任何 以编程方式查询、设置或修改构建级别或设置或 修改违规处理程序。
这意味着将针对合约进行测试的测试程序将需要额外的编译开关。虽然我不喜欢这样,但我理解为什么会这样。更令人担忧的是最后一部分,以及关于它的问题has been raised。如果设置我们自己的合同违规处理程序的能力是实现定义的,那么它在工具链之间将不一致。因此,如果可能的话,对合约的任何测试都不会是可移植的。将它设置为链接器的另一个参数也会很尴尬(而且绝对不可移植)。
目前,无法针对assert 进行测试,因为它只是中止程序,而据我所知,自定义处理程序无法阻止这种情况。对于合约,这应该可以使用自定义处理程序和构建开关来实现,但事实证明,它可能也不可能(或由实现定义)。
或者是否有任何其他方法可以针对断言和合同进行测试,但我可能会遗漏?
【问题讨论】:
-
"目前无法针对 assert 进行测试,因为它只是中止程序,而据我所知,自定义处理程序无法阻止。" 在讨论合同时,他们是一般说的是合约
[[assert:]],而不是宏assert。 -
@NicolBolas 当然是的,但问题几乎相同。不同之处在于调用处理程序时将有一个关闭中止的选项。但是,如果不允许自定义处理程序,则无法检查它是否被调用(违反合同)。