如何改善错误检查和处理能力?


13

最近,我一直在努力了解什么是正确的检查量以及什么是正确的方法。

我对此有一些疑问:

检查错误(错误的输入,错误的状态等)的正确方法是什么?显式检查错误,还是使用可以从最终代码中优化的断言之类的函数,更好?我感觉像是用很多额外的代码来明确地检查程序是否杂乱,无论如何在大多数情况下都不应该执行这些代码,更不用说大多数错误都以中止/退出失败而告终。为什么将具有显式检查的功能弄乱只是为了中止?我一直在寻找断言而不是显式检查错误,却很少能真正解释什么时候做。

大多数人说“使用断言检查逻辑错误,并使用显式检查检查其他故障”。但这似乎并没有使我们走的太远。我们可以说这是可行的:

Malloc returning null, check explictly
API user inserting odd input for functions, use asserts

这会使我在错误检查方面变得更好吗?我还可以做些什么?我真的很想改进和编写更好的“专业”代码。


3
这个问题很好,但是我认为它可能更适合姐妹网站之一(程序员?)。

谢谢,我不确定。我以为,因为它是与代码相关的漂亮工具,所以应该没问题。
Anon

3
简单的答案是“这就是发明例外的原因。获得更好的语言。”
DeadMG

1
@DeadMG:setjmp/ longjmp在C语言中可用,因此您不需要新的语言。
user786653 2011年

3
@DeadMG:不能正确进行C错误检查的人在地狱中获得正确的C ++异常处理的机会非常大……
编码员

Answers:


4

对我而言,最简单的区分方法是确定是在编译时还是在运行时引入错误条件。如果问题是程序员以某种方式使用了错误的函数,请将其声明为引起问题的注意,但是将修订编译到调用代码中后,您无需担心检查它。诸如内存不足或最终用户输入错误之类的问题在编译时无法解决,因此您将检查留在原地。


2

做任何检查在任何时候(可能你上次检查后已经改变),也就是在没有100%命令。还有:在发展过程中甚至不要相信自己!;-)

Okokok ......“什么”是指被解读为检查这样的事情,这将导致一个异常中止或任何可能使你的应用/系统做的事情应该不会做。

认真地说,最后一句话的最后部分至关重要,因为它指出了主要问题:

如果你想建立一个稳定的系统主要关注它不是关于系统应该做什么,而是要让它能够做到这样强制性的东西,一个需要照顾它应该这样做,即使“杂波你码”。


1
为“检查所有内容” +1。我不接受代码混乱的说法:无论如何,任何程序员都应该能够区分错误检查和实际逻辑。
stijn 2011年

2

错误处理的关键不是是否以及如何抓住麻烦。了解它之后您要做的更多。

首先-我会说,没有理由不应该处理从属方法返回的任何单个错误。错误和异常不仅仅是返回值或所有try / catch。

  1. 仅仅投掷和捕捉是不够的。
    参见:作者在其中解释说,仅通过捕获但不采取任何措施就可能抑制异常,并且除非采取了足够的措施来消除损害,否则比让代码像那样做要糟糕。同样,在文件打开或读取错误时仅写入“ log”语句可能会帮助您找到原因-但在程序终止时,可能已导致数据损坏!仅仅说我有很多尝试/捕获是不够的-更重要的是知道他们的实际工作!

  2. 不要滥用尝试。
    有时-大部分懒惰或天真的程序员认为编写足够的try / catch之后,他们的工作就容易了。通常,最好是采取纠正措施并恢复,而不是仅仅丢弃整个事情。如果无法做到这一点,则需要决定您需要返回哪个级别。根据上下文和严重性,尝试捕获嵌套需要仔细设计。例如- 看到这个这个

  3. 定义谁负责:
    您应该做的第一件事就是定义提供给例程本身的输入是不可接受的(或到目前为止尚未处理)方案,还是由于环境(例如系统问题,内存问题)而导致的例外,还是这种情况是算法结果完全内部产生的吗?在所有情况下-您可能想回到的级别或想要采取的措施都大不相同。鉴于此,我想说-当您在生产环境中运行代码时-使abort()退出程序是件好事-但并非对每件事都适用。如果发现内存损坏或内存不足,那么即使您已尽力而为,也肯定会死掉。但是,如果您在输入处收到NULL指针-我不会

  4. 定义什么是最好的可能结果:
    在例外情况下必须做的所有事情非常关键。例如,如果在我们的一种情况下-媒体播放器发现没有完整的数据要向用户播放-它应该怎么做?

    • 要么跳过一些不好的部分,看看它是否可以成功完成。
    • 如果发生太多,请考虑是否可以跳到下一首歌。
    • 如果发现它无法读取任何文件,请停止并显示某些内容。
    • 与此同时
    • 玩家应该在哪个状态下向用户弹出
    • 什么时候应该自己进行?
    • 是否应该“停止”请求用户反馈
    • 还是应该在某个角落放一些不显眼的错误提示?

    所有这些都是主观的,也许解决问题的方法比我们琐碎的事情更多。以上所有这些都需要构建和理解异常的深度,并且还应该使不同的场景可能演变为异常。

  5. 有时我们需要在异常出现之前检查异常。最常见的例子是除以零误差。理想情况下,必须在引发此类异常之前进行测试(如果是这种情况),请尝试放置最合适的非零值并继续前进,而不要自杀!

  6. 清理。至少这是您必须做的!如果某个函数碰巧会打开3个文件,而第四个文件无法打开-不用说前3个文件应该已经关闭。将这项工作委派给上一层是一个坏主意。如果您决定不要不清理内存就离开。最重要的是-即使您在例外情况中幸免于难,也要告知高层,事情还没有正常进行。

我们从各种层次结构,层或抽象的角度看待软件(正常)功能的方式,我们必须根据异常的严重性以及异常发生的范围以及它们影响系统其他部分的方式对异常进行分类如何以最好的方式处理这些不同的异常。

最佳参考:Code Craft第6章-可供下载


1

仅在调试构建过程中检查错误是BAD IDEA(tm),在发行版本下进行编译会在堆栈上覆盖可重用的变量,删除保护页面,对计算进行一些棘手的技巧,用预先计算的班次替换繁琐的操作,等等。

在发行版中也使用错误检查,您可以采用以下简单方法:

if(somethinghitthefan)
     abort();

这也有很好的副作用,一旦应用程序开始在betta测试仪PC上崩溃,您肯定不会忽略该错误。

与相比abort(),事件查看器和日志是完全无用的,谁来检查它们?


退出/中止==有史以来最糟糕的用户体验:应用程序消失了而没有告诉原因..
stijn 2011年

@stijn:abort闯入调试器/创建转储。exit不好,是的。虽然,我__asm int 3最喜欢。
编码器

的确如此,在C / C ++中,我也倾向于使用__asm int 3编写断言,但绝不会不显示原因的描述,最好还包括行和文件。然后至少客户可以提供有关确切发生的情况的信息。
stijn 2011年

0

您可以做的各种事情是:1
.在线阅读和吸收大量代码,并了解其工作方式
。2.使用一些调试工具,以帮助您定位错误区域
。3.注意由于分配不当而造成的小错误。语法错误。
4.由于程序中的逻辑错误而导致的一些更严重的错误难以找到。为此,您可以将其找出并查找,或者对于更复杂的错误,请尝试与人们交谈或使用StackoverflowWikipediagoogle等资源来获取帮助人。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.