C++ 错误处理——示例代码的良好来源?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/231128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ Error Handling -- Good Sources of Example Code?
提问by Head Geek
Just about every piece of example code everywhere omits error handling (because it "confuses the issue" that the example code is addressing). My programming knowledge comes primarily from books and web sites, and you seldom see any error handling in use at all there, let alone good stuff.
几乎每个地方的每段示例代码都省略了错误处理(因为它“混淆了示例代码正在解决的问题”)。我的编程知识主要来自书籍和网站,你很少在那里看到任何错误处理的使用,更不用说好东西了。
Where are some places to see good examples of C++ error handling code? Specific books, specific open-source projects (preferably with the files and functions to look at), and specific web pages or sites will all be gratefully accepted.
哪里可以看到 C++ 错误处理代码的好例子?特定的书籍、特定的开源项目(最好带有要查看的文件和功能)以及特定的网页或站点都将被感激地接受。
回答by fhe
Herb Sutter's and Andrei Alexandrescu's book C++ Coding Standardscomes with a whole chapter on Error Handling and Exceptionsincluding
Herb Sutter 和 Andrei Alexandrescu 的书C++ Coding Standards有一整章关于错误处理和异常,包括
- Assert liberally to document internal assumptions and invariants
- Establish a rational error handling policy, and follow it strictly
- Distinguish between errors and non-errors
- Design and write error-safe code
- Prefer to use exceptions to report errors
- Throw by value, catch by reference
- Report, handle, and translate errors appropriately
- Avoid exception specifications
- 自由断言以记录内部假设和不变量
- 建立合理的错误处理政策,并严格遵守
- 区分错误和非错误
- 设计和编写错误安全代码
- 更喜欢使用异常报告错误
- 按值抛出,按引用捕获
- 适当地报告、处理和翻译错误
- 避免异常规范
Every topic also includes an example and I found it to be a very valuable resource.
每个主题还包含一个示例,我发现它是非常宝贵的资源。
回答by gbjbaanb
"Use exceptions"vs. "Use error codes"is never as clear-cut as examples suggest.
“使用异常”与“使用错误代码”从来没有像示例所暗示的那样明确。
Use error codes for program flow. If you have an error that is expected, do not throw an exception. E.g. you're reading a file, you may throw an exception for "file not found", "file locked"; but never throw one for "end of file".
使用程序流程的错误代码。如果您有预期的错误,请不要抛出异常。例如,您正在读取一个文件,您可能会抛出“未找到文件”、“文件已锁定”的异常;但永远不要为“文件结尾”抛出一个。
If you do, you can never write simple loops, you'll always wrapping code in exception handlers. And don't forget exceptions are very slow, this is especially important in big multi-threaded servers. (Not so important at all in your desktop application).
如果这样做,您将永远无法编写简单的循环,您将始终将代码包装在异常处理程序中。并且不要忘记异常非常慢,这在大型多线程服务器中尤其重要。(在您的桌面应用程序中根本不重要)。
Secondly, be very careful with exception hierarchies. You may think it's OK to have an Exception
class, then derive a NetException
from it, then SMTPException
for your SMTP class. But unless you hold generic data in the base class, you will always have to catch every type of exception in that hierarchy. E.g. if you put the reason for the SMTP error in your SMTPException
class, you must catch it - if you only catch Exception
types, you will not have access to the SMTPException
members. A good workaround for this problem is to have a string and an int member in the base exception class and only use them, even for the derived types. Unfortunately std::exception
only offers a string :(
其次,要非常小心异常层次结构。您可能认为可以有一个Exception
类,然后NetException
从它派生一个,然后SMTPException
用于您的 SMTP 类。但是除非您在基类中保存通用数据,否则您将始终必须捕获该层次结构中的每种类型的异常。例如,如果你把 SMTP 错误的原因放在你的SMTPException
类中,你必须抓住它——如果你只抓住Exception
类型,你将无法访问SMTPException
成员。这个问题的一个很好的解决方法是在基异常类中有一个字符串和一个 int 成员,并且只使用它们,即使对于派生类型也是如此。不幸的是std::exception
只提供一个字符串:(
Some people say that doing this means you might as well only have a single exception type, especially as you will always catch the base class type anyway.
有些人说这样做意味着您可能只有一个异常类型,尤其是因为无论如何您总是会捕获基类类型。
If you do use exceptions you must take the trouble to populate them with more data than you would with an error code. With errors, you must handle them immediately or they get lost in the code. With an exception, it may get caught many levels away from where it was thrown - like in Roddy's example. DoC
is called, and gets an exception 2 levels in from DoA
. Unless you specify the error to be specific to the code in DoA
, you may think it was thrown from the DoB
function. (simple example, but I've seen code where an exception was handled many levels down the call stack. It was a bstrd to debug. This especially applies to OO programs)
如果你确实使用了异常,你必须费心去用比错误代码更多的数据来填充它们。对于错误,您必须立即处理它们,否则它们会在代码中丢失。除了一个例外,它可能会在离它被抛出的地方很多层的地方被捕获——就像在 Roddy 的例子中一样。DoC
被调用,并在 from 中获取 2 个级别的异常DoA
。除非您指定特定于 中的代码的错误,否则您DoA
可能认为它是从DoB
函数中抛出的。(简单的例子,但我看到其中一个异常被处理了许多水平下降调用堆栈的代码,这是AB ST次调试。这尤其适用于面向对象程序)
So hopefully, I've given you enough to think about. The simple truth of the matter is that style means nothing in error handling, practicality is everything. If you have to put log statements everywhere an error can occur, then do so. It matters a lot more that you can see where the code went wrong (and what data was being worked with) than you have a elegant exception hierarchy or you've littered your code with exception handlers. If you cannot easily trace the error, your error handling code is useless.
所以希望,我已经给了你足够的思考。事情的简单事实是,风格在错误处理中毫无意义,实用性就是一切。如果您必须在可能发生错误的任何地方放置日志语句,请执行此操作。与拥有优雅的异常层次结构或在代码中放置异常处理程序相比,您可以看到代码出错的地方(以及正在处理的数据)更重要。如果您无法轻松跟踪错误,那么您的错误处理代码将毫无用处。
Exceptions are good, use them. But think about what you're doing, do not misuse or overuse them. A misused exception is worse than no error handling at all (as you can grab a crash dump and view the unhandled exception to find the error in seconds. With an exception that is eaten and ignored, you're stuffed).
例外很好,使用它们。但是想想你在做什么,不要误用或过度使用它们。误用的异常比根本没有错误处理更糟糕(因为您可以抓取崩溃转储并查看未处理的异常以在几秒钟内找到错误。如果异常被吃掉并被忽略,您就饱了)。
I've found over the years that the biggest assistant to debugging is logging. Write logs, write lots of logs.
多年来,我发现调试的最大助手是日志记录。写日志,写很多日志。
回答by Steve
I prefer the exception handling discussed in this article. It results in clean code and avoids explicit creation/deletion of objects just to process exceptions. http://www.informit.com/articles/article.aspx?p=373339
我更喜欢本文中讨论的异常处理。它会产生干净的代码并避免仅为了处理异常而显式创建/删除对象。 http://www.informit.com/articles/article.aspx?p=373339
回答by Roddy
With C++, you should end up with less visible error handling code anyway, because you can leave a lot of the heavy lifting to Exceptions.
使用 C++,无论如何你应该得到不那么明显的错误处理代码,因为你可以把很多繁重的工作留给异常。
In my opinion the most basic rule with exceptions (and one most commonly broken) is this. Don't try to catch exceptions unless you have a specific plan to handle them.
在我看来,除了例外(也是最常被破坏的规则)的最基本规则是这样的。 除非您有处理异常的特定计划,否则不要尝试捕获异常。
With exceptions, you don't have to worry about error codes returned from functions, because well designed functions will just throw exceptions instead.
对于异常,您不必担心函数返回的错误代码,因为设计良好的函数只会抛出异常。
In C a typical error handling scenario looks like this:
在 C 中,典型的错误处理场景如下所示:
int DoA()
{
if (location == hellInAHandcart)
return ERROR;
else
RETURN OK;
}
int DoB()
{
int err = DoA();
if (err != OK)
return err;
else
return DoSomethingElse1();
}
int DoC()
{
int err = DoB();
if (err != OK)
//Handle My error here in whatever way...
}
While in C++...
在 C++ 中...
void DoA()
{
if (location == hellInAHandcart)
throw Exception("Gone To Hell in a Handcart");
}
void DoB()
{
DoA();
DoSomethingElse1();
}
void DoC()
{
try
{
DoB();
}
catch (Exception &E)
{
// Handle My error here in whatever way...
}
}