【问题标题】:How to handle improper input files如何处理不正确的输入文件
【发布时间】:2013-04-01 11:56:58
【问题描述】:

我正在启动一个项目,我想知道在文件输入处理期间处理错误的最佳实践。我目前对该项目的计划涉及main 中的一个流程,大致如下:

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

// Do real work here

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

#ObjectA-1

ObjectA 告诉我我有一个文件要转换为满足InterfaceA 的对象,1 告诉我要使用该接口的哪个具体实现。

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

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

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

如果不是为了使用exit 函数,我个人更喜欢第二个。

【问题讨论】:

  • 既然您使用的是 C++,您是否有理由不使用 RAII?
  • 老实说,我会把所有这些行都写成Configuration config(argc, argv); InterfaceA a(config);。无需内存管理。
  • 问题是我需要逻辑来确定要创建哪种类型的A
  • @GodricSeer 哦,好吧,然后Configuration config(argc, argv); shared_ptr&lt;InterfaceA&gt; a(InterfaceA::fromConfig(config));
  • @sftrabbit 我知道使用 shared_ptr 会消除我的内存管理,但是我不理解a(InterfaceA::fromConfig(config))。 InterfaceA 有纯虚方法,所以我不能以这种方式拥有它的构造函数。

标签: c++ exception


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 2012-11-09
    相关资源
    最近更新 更多