异常、错误代码、断言
我正在开发一个生成设备报告的库。 generate_report (const std::string& no)
成员函数可能因各种原因而失败:
- 无效的报告号。
- 无效状态(
report_generator
是 FSM) - 没有设备处于活动状态
- 报告生成期间
错误哪种错误处理机制最适合这些错误?
- 只需返回
true
或false
- 返回错误代码
- 断言和日志
- 抛出异常
- 上述任何组合
一些上下文信息:正常工作流程如下。用户激活设备,从列表中选择报告并单击“生成”。
编辑:感谢到目前为止的回复!对我来说,现在很清楚何时使用断言以及何时进行错误处理。对于错误处理,错误代码和异常各有利弊。我想我会寻求例外(并为上述错误创建四个类),但我还没有真正相信。我总是想到“意外情况”的例外情况。无效的报告号并不意外。有什么建议吗? :)
I'm working on a library that generates reports of devices. The generate_report (const std::string& no)
member function can fail due to various reasons:
- invalid report no.
- invalid state (the
report_generator
is a FSM) - no device is active
- error during report generation
Which error-handling mechanism is best for these errors?
- just return
true
orfalse
- return error code
- assert and log
- throw exception(s)
- any combination of the above
Some context information: the normal workflow is as following. The user activates a devices, chooses a report from a list and clicks on "generate".
EDIT: Thanks for the replies so far! For me it's clear now when to use asserts and when to do error-handling. As for error-handling, error codes and exceptions both have pros and cons. I think I go for exceptions (and create four classes for the above errors), but I'm not yet really convinced. I always thought of exceptions of 'unexpected situations'. An invalid report no isn't really unexpected. Any advice? :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
其中任何一个都有不同的目的:
错误代码版本。异常:异常和错误代码代表了如何处理结果代码的不同习惯用法。异常更加强大 - 结果代码可以被忽略或丢失。库通常应该强烈区分抛出异常的位置/内容以及何时使用错误代码。最好只使用两者之一。
返回
true
或false
:错误代码的特殊化。通常是最糟糕的想法 - 只有当没有比好或坏更多的内容报告时才好(即
malloc
返回好或坏(=NULL
)。断言和日志:这些是调试技术,不应该用作向用户/客户端的报告机制。断言只是说“发生了一些事情,我无法处理 - 我退出”。
Any of these have different purposes:
error code vers. exception(s): exceptions and error codes represent different idioms of how result codes shout be handled. Exceptions are more robust - result codes can be ignored or lost. A library should usually strongly distinguish where/what exceptions are thrown, and when error codes are used. At best, use only one of both at all.
return
true
orfalse
: A specialization of error codes.Usually the worst idea - only good if there is no more to report than good or bad (i.e.
malloc
returns either good or bad (=NULL
).assert and log: These are debugging techniques, and should not be used as report mechanisms to users / clients. Asserts just say "something happened, that I can not handle - I quit".
断言不是正确的选择。当你有不变量时使用断言;一些不应该发生的事情。不要做像断言()这样的事情,如果参数是错误条件而不是不变量,则参数永远不会为空。
如果是我,我会在接口中使用异常,并且如果必须的话,如果内部使用的函数不使用异常,则通过内部使用的函数来翻译错误代码。只要保持一致(并且不要对这些东西使用断言)。
assert is not the right choice. Use assert when you have an invariant; something that should never happen. Don't do things like assert() that an argument will never be null if it is an error condition and not an invariant.
If it were me, I would use exceptions in the interface and, if I had to, translate error codes by functions used internally if they do not use exceptions. Just be consistent about it (and don't use assert for this stuff).
与真/假和错误代码相比,异常有几个重要的优点:
断言用于表达代码中的前提条件等内容,并有望在开发过程中发现任何错误。但是,您不应依赖发布代码中的断言,并且出于性能原因,断言通常会从发布代码中删除。
Exceptions compared to true/false and error codes have several important advantages:
Asserts are used to express stuff like preconditions in your code and will hopefully uncover any bugs during development. However, you should not rely on asserts in your release code, and for performance reasons asserts are normally removed from release code.
我建议阅读 Boost 社区关于异常和错误处理的指南 [boost.org]。
I recommend reading the Boost community guide [boost.org] to exceptions and error handling.
选择什么策略通常取决于品味。我说选择最适合您图书馆客户的产品。如果他们采用例外策略,就使用例外。如果他们习惯了错误代码,请坚持使用。
It is often a matter of taste what strategy to choose. I say pick up what best integrates with the clients of your library. If they adopt exception strategy, use exceptions. If they are accustomed to error codes, stick with it.
您所报告的设备的可靠性如何?
我问这个问题是因为对于一大类设备来说,未连接、未打开、电池耗尽、忙于做其他事情等等都是相当正常的状态。
如果是这种情况,如果设备因某种原因不可用,我会倾向于返回状态代码(注意不是错误代码)。
另一方面,如果您认为这些设备超级可靠,并且它们不响应确实是例外,那么异常处理可能是正确的选择。
mutch 作为“异常”实际上只是一种编写“if (x != 0) { goto error_routine; ”的奇特方式,这并不重要。但是,我个人更喜欢异常处理来处理异常情况,而不是像 end_of_file 这样的常规事件。
How reliable are the devices you are reporting on?
I ask because for a large class of devices not connected, not switched on, out of batteries, busy doing something else etc. etc. are fairly normal states.
If this is the case I would favour returning a status code (note not an error code ) if the device is somehow unavailable.
If on the other hand you consider these devices super reliable and it really is exceptional for them not to respond then exception handling may be the way to go.
It doesn't really matter that mutch as 'exceptions' are really just a fancy way to code 'if (x != 0) { goto error_routine; }, but, I personally prefer exception handling to deal with exceptional situations not routine events like end_of_file.
我将违背常规并建议错误代码和异常,但这只是因为您正在创建一个库。既然你说你正在创建一个库,我猜这个库将可供你无法控制的人编写的代码使用。因此,使您的代码对不同的编译器甚至语言都友好是一件好事。
因此,我将编写一个 C++ 异常库并提供详细说明异常类的头文件。我还将编写一个 C 接口来为用户处理异常。现在用户可以链接到任何合适的接口:
C 实现调用 C++ 实现:
I'm going to go against the grain and suggest both error codes and exceptions, but only because you are making a library. Since you say you are making a library, I'm guessing that library will be made available to code written by people you have no control over. So, making your code friendly to different compilers and possibly even languages is a good thing.
So I would code a C++ exception library and provide header files detailing your exception classes. I would also code a C interface that handles the exceptions for the user. Now the user can link against which ever interface is appropriate:
The C implementation calls the C++ implementation:
2c
2c
首先——保持一致!
第二:
First - be consistent!
Second: