我目前正在为一段代码添加处理,以便它不会崩溃。目前,每个步骤都有一个ASSERT语句,以确保在上一步中没有出错。如果在其中一个步骤中出现问题,则确实出现了问题。该计划应该停止。
虽然在发布模式下程序会命中一个断言,然后快乐地继续前进并崩溃。
为了解决这个问题,我已将该方法包装在try / catch块中,并在以前的断言处抛出错误。这应该记录我们跟踪的所有错误以及其他我们没有记录的错误。
现在我的问题是,我是否还应该使用断言通知程序员这不应该发生?或者现在它们会因为catch块(我清理对象)而不会崩溃?
或者我应该只在catch块中抛出一个断言而不是每个throw语句?
答案 0 :(得分:14)
try
& catch
和assert
的目的完全不同(至少在我看来)。
try
和catch
用于处理预期的错误情况(用户提供的文件名不存在,调用新的不能分配内存,用户输入的无效输入某种等等。)
assert
的目的是保证程序员不会犯错误。希望在发布时运行代码时,您已经涵盖了这些替代方案,并且知道代码是好的"。 assert
的典型示例是用户不应提供的指针,因为NULL
确实不是NULL
,或者链表具有预期的节点数[例如}你计算remove_node
之前的节点数,并检查节点的数量确实少了一个]。
如果您不是100%确定(或者至少98.75%确定或您决定的任何级别"足够好")您已经测试了所有代码,那么您不应该发布 - 或者,如果你这样做,请让你的质量保证经理签署"我们还没有做足够的测试,但我们对此很好。"。
try
和catch
只应用于您的程序可以可靠地恢复的内容。不要抓住"程序员写了导致崩溃的愚蠢代码"。
编辑以澄清实际答案:
换句话说,是的,您应该使用assert
来表示您不希望在代码中发生的事情[至少如果程序员没有做错事] - 这包括例如例如,当你期望有一个方形矩阵或者指针不是NULL
时,检查矩阵向量内的向量确实是一个正方形[除了你期望它们的位置 - 甚至可能检查一下他们应该是NULL
。
当出现问题时,您应该使用try
/ catch
和throw
进行错误检查,这可能会在实际程序运行期间发生,现实生活中&#34 34; - 磁盘已满(或只读),文件不存在,内存不足,等等。
答案 1 :(得分:3)
Mats Petersson在assert
上非常正确。它的使用是预发布,以检查您的内部逻辑。我不会重复这一点。
但是,我要添加的是,我们假设您要检查其他内容 - 例如,检查应该永远不会出错的内容的结果,但可能会例如,由于系统其他部分的问题。在这种情况下,您应该检查它(不使用assert
),并优雅地处理这种情况。通常情况下,throw
是一个例外,因为你没有(通常)希望程序在没有错误的情况下停止运行。或者事物本身抛出异常。通常你想要以干净的方式继续,但如果你想要停止,你几乎肯定想先做一定程度的清理。那就是你的catch
阻止等意图。
答案 2 :(得分:2)
我认为您使用断言宏,在发布模式时排除了,这就是您的代码通过它们快乐运行的原因。它们主要用于一种调试,在开发过程中确保您的程序运行良好。
想想他们就像他们说的那样:
这应该永远不会发生在这里,如果它发生在我的代码中有一个错误, 所以我必须解决它
他们告诉你,你犯了(逻辑)错误。
例如,当您检查零除数时:
int x = GetIntFromInput();
if (x != 0);
{
assert(x != 0);
float y = 10.0f / x;
}
此代码有一个语义错误,条件后面的;
。这个断言会在调试/开发构建过程中警告你。
如果你想创建'run-time'断言,只需使用try / catch块,但是我真的不喜欢抛出它们。 Why should I not wrap every block in "try"-"catch"?。也许您可以使用if
- s或错误代码替换例外。
答案 3 :(得分:2)
防御性编程包括在每行代码中定义您的假设,仍然检查它们。
Assert
应该解释“此时,我真的相信这种情况失败将表明系统处于程序员(我)不期望的状态”。
让代码也检查假设的失败,并提前退出,是防御性编程的一个例子。但是这些失败只应发生在特殊的单元测试中,这些测试打破了各种接口的前提条件(禁用断言)。如果它发生在正常的单元测试中,或者在正常使用中,或者在用户系统上,那么您需要在其他地方移动保护以防止故障,或者使故障成为预期的故障模式。
根据断言的严重程度,如果情况出现极端错误,你应该抵制“跛行”的诱惑。应该以可以恢复的方式备份程序的状态,应该通知用户并鼓励用户关闭程序。如果您的程序可以执行不可逆转的操作,则强制关闭更合理。
答案 4 :(得分:1)
我刚刚意识到问题没有得到回答。我将解决这个问题,而不是关于断言和异常应该和不应该做什么的另一个讲座:"现在我的问题是,我是否应该使用断言通知程序员这不应该发生?& #34;
答案是记录。这应该会触发一个错误日志,这个日志很容易在客户站点上显示,或者至少对您的任何人提供技术支持。