错误处理:区分“致命”和“致命”错误和“意外输入”错误
我一直在开发一个读取 XML 文件的程序,如果 ifstream 无法打开该文件,它将抛出 std::ifstream::failure。每当设置 std::ifstream::failbit 或设置 std::ifstream::badbit 时都会引发此异常,并且它们(至少在我看来)是需要异常处理的错误类型。
打开文件后,我使用RapidXML创建DOM对象,如果失败,它的解析函数将抛出rapidxml::parse_error。在这种情况下,错误并不是真正致命的——它只是错误的输入。无论如何,我认为rapidxml在解析xml文件失败时抛出异常仍然是公平的,但即使我不这么认为,也并不重要,因为我没有太多选择。我可以关闭 RapidXML 中的异常,但是我仍然必须手动处理这些异常情况,而且通过异常机制处理它们要容易得多。然而,这绝对是一个黑暗的领域; rapidxml::parse 抛出异常的理由并不像 ifstream 那样明确。
最后一种情况是当我解析 DOM 时遇到意外或意外的节点。显然,尽管有意外输入,程序仍可以继续执行,但我不希望它这样做。我可以想象在这里抛出一个异常,但我不确定这是否有意义。
因此,我请求一些建议:异常处理的最佳实践是什么?我尝试在类中使用 RAII 习惯用法,通过在构造函数中执行所有这些操作来解析文件。我使用 boost::shared_ptr 来实例化文件解析类,因此如果构造函数抛出异常,boost::shared_ptr 将在删除文件解析类后重新抛出 std::bad_alloc 。
当 XML 文件不符合此类的期望时,我可以提出一个论据,认为发生这种情况是有意义的,并且我认为在出现意外输入时抛出异常是有意义的,但我真的只是想确保我的思维过程是正确的。
I've been working on a program that reads in an XML file, and if ifstream is unable to open the file, it will throw std::ifstream::failure. This exception is thrown whenever std::ifstream::failbit is set or std::ifstream::badbit is set, and they are (at least in my opinion) the type of errors that warrant exception handling.
After I open the file, I use RapidXML to create the DOM object, and its parse function will throw rapidxml::parse_error if it fails. This is the type of situation where the error isn't really fatal--it's just bad input. At any rate, I think it's still fair for rapidxml to throw an exception when it fails to parse the xml file, but even if I didn't think so, it doesn't really matter, because I don't have too many options. I could turn off exceptions in RapidXML, but then I'd still have to handle these exceptional cases manually, and it's just far easier to handle them via the exception mechanism. However, this is definitely a murky area; the justification for rapidxml::parse to throw exceptions isn't as clear-cut as it is for ifstream.
The final case is when I'm parsing the DOM and come across an unexpected or unanticipated node. Clearly, the program can continue executing in spite of unexpected input, but I wouldn't want it to. I could conceivably throw an exception here, but I'm not sure if that makes much sense.
So, I'm asking for a little advice: what are some best practices for exception handling? I try to use the RAII idiom in the class that parses files by doing all of this in the constructor. I use a boost::shared_ptr to instantiate the file parsing class, so if the constructor throws, boost::shared_ptr will rethrow std::bad_alloc after delete'ing the file parsing class.
I can make an argument for having this occur when the XML file doesn't conform to what this class expects, and I suppose it would make sense to throw an exception when presented with unanticipated input, but I'd really just like to make sure that my thought process is correct.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你的设计对我来说很有意义:完全初始化或抛出异常。想到的唯一替代方案是:
对于全有或全无方法想到的唯一缺点是处理“几乎正确”的输入。如果缺少属性,应用程序可能更喜欢默认值。
Your design makes good sense to me: Initialize completely or throw an exception. The only alternatives which come to mind are:
The only disadvantage which comes to mind for the all-or-nothing approach is dealing with "almost correct" input. Maybe the application would prefer a default value if an attribute is missing.