处理错误

描述 C++ API 中的错误处理。

在 Concert Technology 中,对两类错误进行了区分:

  • 编程错误,例如:

    • 访问空句柄对象;

    • 混合来自不同环境的建模对象;

    • 访问数组大小以外的 Concert Technology 数组元素;以及

    • 将大小不兼容的数组传递给函数。

      此类错误通常是因为程序员疏忽所致。 确定并修正这些错误通常不会有损坏应用程序的危险。 在生产应用程序中,不必处理这些类型的错误。

      在 Concert Technology 中,此类错误条件是使用断言语句加以处理。 如果是在未指定 -DNDEBUG 的情况下进行编译,那么将执行错误检查,代码将中止,并发出错误消息以指示哪项断言失败。 然后,应该在指定 -DNDEBUG 编译器选项的情况下编译生产应用程序,这将移除所有检查。 换言之,检查断言不会耗用任何 CPU 周期。

  • 运行时错误,例如内存耗尽。

    正确的程序假定可能会发生此类故障,因此必须加以处理,即使在生产应用程序中也是如此。 在 Concert Technology 中,如果发生此类错误情况,那么将抛出异常。

Concert Technology 类(包括 IloCplex)所抛出的所有异常都是从 IloException 派生。 算法类(例如 IloCplex)所抛出的异常是从其子级类 IloAlgorithm::Exception 派生。 CPLEX 所抛出的最常见异常是从 IloCplex_ExceptionIloAlgorithm::Exception 的子级类)派生的。

异常类 IloCplex::Exception 的对象对应于 CPLEX Callable Library 所生成的错误码。 可通过调用以下方法来查询所捕获到的异常中的错误码:

IloInt getStatus () const;

可通过调用以下方法来查询错误消息:


const char* IloException::getMessage() const;

此方法是从基类 IloException 继承的虚方法。 如果您只希望访问消息以便列显到通道或输出流,那么更方便的做法是使用 Concert Technology 为 IloException 提供的重载输出运算符 (operator<<)。

除了与 C Callable Library 中的错误码相对应的异常以外,cplex 对象还可抛出仅与 IloCplex 相关的异常。 例如,如果抽取的模型包含多个目标函数,那么将抛出 MultipleObjException 异常。这样的附加异常类是从类 IloCplex_Exception 派生的;可通过调用 getStatus 方法时返回的负状态码来识别对象。

与大多数其他 Concert Technology 类不同,异常类不是句柄类。 因此,如果通过值而非引用来捕获异常(即,使用 catch(IloException& e) {...}),那么该异常的正确类型将丢失。 这就是通过引用来捕获 IloException 是一种好想法的其中一个原因,所有示例都演示了这种做法。 例如,请参阅 ilodiet.cpp。 某些派生异常可能包含通过值捕获时将会丢失的信息。 因此,与输出通过值捕获到的异常相比,输出通过引用所捕获到的同一异常可获得更加准确的消息。

通过引用来捕获异常还有一种原因。 某些异常包含数组,以传达无法调用函数的原因。 如果通过值调用该异常时丢失此信息,就无法针对此类数组调用 end 方法,它们的内存将泄露(直至调用 env.end 为止)。 通过引用捕获异常之后,调用该异常的 end 方法将释放所抛出实际异常的数组(或表达式)所可能使用的所有内存。

总之,捕获异常的首选方法如下:


catch (IloException& e) {
  ...
  e.end();
}

其中,IloException 可以替换为期望的 Concert Technology 异常类。