在谈论错误处理时我有些困惑。 以Direct2D为例。 在我们开始使用Direct2D功能之前,我们必须创建一个ID2DFactory对象:
HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2d1Factory);
从上面可以看出。我们可以检查HRESULT hr以查看我们是否已成功创建ID2DFactory。 我认为当这个调用失败时,即使我再次调用它,它仍然会失败。我们没有任何方法可以从这次失败中恢复过来。
那么检查返回值有什么意义呢?是否可以在终止程序之前告诉用户出现了什么问题?
另一个例子是内存不足。当我们遇到一个罕见的场合,我们没有足够的内存让我们的程序“新”某些对象。 在C ++中,当内存不足时,new运算符可能返回NULL或引发错误。如果您不测试它是否为NULL,也没有捕获错误,则程序将终止。我不认为你的程序可以从这种情况中恢复过来。
再说一次,检查是否存在严重错误而你无能为力是什么意思?
答案 0 :(得分:4)
首先,并非每个错误都无法恢复。示例:如果用户想要打开的文件不可用,程序可能希望将此情况报告给用户并要求打开另一个文件。
其次,即使程序无法继续,它也必须有机会正常终止,通知用户有关问题,保存状态,记录问题以备将来分析等,而不仅仅是崩溃。如果没有错误检查,程序很可能会崩溃。
答案 1 :(得分:2)
曾经有过客户的错误报告说“它刚刚崩溃”?当错误报告包含错误对话框的屏幕截图,说“D2D1CreateFactory返回E _...”时,它们会更有用。
答案 2 :(得分:1)
像D2D1CreateFactory()这样的初始化函数可能会失败。这种故障通常意味着您的PC上的操作系统已完全消耗,您需要重新启动。这些信息对于用户来说很有价值,他们想知道“O / S被重新启动,重新启动并再次尝试”而不是“在模块mod.c中的2345中取消引用nil”。如果您没有捕获错误条件,那么您所知道的只是程序崩溃了。
捕获错误返回和异常,并将其报告给用户是将好程序与差程序分开的众多因素之一。
特别是对于new,您的程序通常有很多选择。它可能能够重新请求较小的初始内存块。它可能能够返回保存缓存值的内存并重试。它可能能够保存文件以准备退出,这也具有返回内存的效果。
当您处理错误返回或异常时,您有四个选择;中止,交替,重试,失败。
中止是清理并退出;最好是返回资源,关闭文件,以及保存在制品。
替代是尝试一种完全不同的做同样事情的方法;喜欢尝试ftp,如果你不能使用http。交替是最难的错误恢复方法,坦率地说,大多数情况下只有NASA有预算编码这种错误处理。
要重试,只需再次尝试相同的操作即可。如果故障是暂时的,这可能是成功的。如果失败是持久的,重试可能导致无限循环,因此最好使用限制计数器或指数增加的时间延迟来重试。
失败就是简单地删除请求或操作并尝试处理下一个请求。失败可能看起来很愚蠢,因为它意味着未执行请求,未更新屏幕或忽略用户输入。但令人惊讶的是,用户可以通过在程序外部执行某些操作来恢复此类错误,或者在情况不同时再次尝试。在大多数情况下,如果程序终止,它会完全拒绝为用户提供服务,而用户可能能够使用损坏或部分正确的程序。 (试着设想一个飞行控制系统因为它取消引用而中止而中止。这不是你想要的。)
答案 3 :(得分:0)
可能有很多事情要清理,比如打开文件句柄,或者某些数据库操作要回滚等,如果出现错误需要执行。在某些情况下,错误可能并不重要,程序可能只继续使用部分功能而不是完全崩溃。最后但并非最不重要的是,它提供了有关错误发生位置的宝贵信息,这对调试非常重要。
顺便说一句,除非你使用的是一些不符合要求的古老编译器,new
不能按照C ++标准返回NULL,否则它必须在失败的情况下抛出std::bad_alloc
异常。
答案 4 :(得分:0)
检查返回值等对于调试始终至关重要。只需使用宏。
答案 5 :(得分:0)
图像两个每个都遇到错误的程序。
由于内存不足或其他原因造成一次崩溃,导致非法使用内存,操作系统显示一些模糊的错误,或者只是默默地关闭程序。
另一个应用程序显示更简单的错误消息,然后回滚导致错误的操作,以便您可以决定是否要继续和/或尝试解决导致错误的条件。 (例如,关闭其他一些应用程序可能会有更多内存。)
您更喜欢使用哪个程序?