0

我正在开始一个项目,我想知道在文件输入处理期间处理错误的最佳实践。我目前对该项目的计划涉及以下过程main

unique_ptr<Configuration> config(initConfig(argc,argv));
unique_ptr<InterfaceA> a(initA(config));

// Do real work here

配置类和所有其他类的初始化数据将包含在其输入文件的标头中,例如:

#ObjectA-1

ObjectA告诉我我有一个文件打算变成一个满足的对象,InterfaceA并且1告诉我要使用该接口的哪个具体实现。

initConfig我的问题是对和等函数的错误处理initA。在这些函数中,我将解析它们各自文件的第一行,并解码上述信息。比方说,如果initA我碰巧得到一个没有适当标题的文件,无论是它#ObjectB-3,还是根本没有标题。我看到了两种处理错误的方法:

  • 抛出将在 main 中捕获的异常。这将允许我打印错误,然后通过错误标志绕过其他初始化函数,并进行任何我需要的高级清理。不好的部分main是它们主要由异常处理组成,这使得代码更难阅读。

  • 从 init 函数内部打印一个错误,然后调用exit(EXIT_FAILURE)并依靠我的操作系统来清理以前分配的内存。这可能会导致更简洁的代码和更多的本地错误处理。

如果不是为了使用该exit功能,我个人更喜欢第二种。

4

1 回答 1

1

我使用以下规则来执行错误处理:

  1. 如果可以的话,调用代码是否应该处理异常事件?如果是,则抛出异常。有时“异常”很难定义,所以更像是“这应该发生吗?” 我认为在这种情况下,您应该抛出异常,并且main应该在有意义的情况下处理它们。

    该标准定义了两组例外情况。首先是那些继承自std::logic_error. 当调用代码违反了你的函数契约时,通常会抛出这些。然后是那些继承自 的std::runtime_error,用于只能在运行时检测到的错误。这听起来和你的一模一样。它只有在读取文件时才知道文件有问题。

    当然,如果你愿意,你可以抛出你自己的异常类型。

  2. 它是被认为是正常的并且可能被调用代码忽略的错误吗?这可能是错误代码的适当使用。

  3. 这是您的代码内部的逻辑错误吗?这更有意义assert。您应该使用asserts 来验证您正在做的事情是否真的有意义。一个愚蠢的例子是int y = 5; y++; assert(y == 6);。将其视为防止愚蠢错误的保险。

正如我所说,您的问题听起来像是使用异常的好地方。如果正确使用 RAII,内存分配绝对没有问题。也就是说,所有的内存释放都应该在对象的销毁中完成。即使抛出异常,仍会调用析构函数。

于 2013-04-09T22:51:51.780 回答