C++ 处理C+中基类重写方法的异常+;

C++ 处理C+中基类重写方法的异常+;,c++,c++11,exception-handling,C++,C++11,Exception Handling,我正在编写一个程序(实际上是一个库),它应该对给定的数据集进行某种处理。这个程序有一个插件机制。每个插件对数据遵循不同的处理策略。这个想法是,用户可以在插件中创建自己的处理策略,而不必触摸程序的代码。该软件是基于服务器的应用程序,永远不会终止。问题如下:如果用户提供了自己的插件,但其代码抛出了未处理的异常,该怎么办?这将使应用程序崩溃,服务器将脱机。鉴于插件总是创建一个从库和插件都可见的类派生的对象,显而易见的解决方案是: class AbstractSolver { public: v

我正在编写一个程序(实际上是一个库),它应该对给定的数据集进行某种处理。这个程序有一个插件机制。每个插件对数据遵循不同的处理策略。这个想法是,用户可以在插件中创建自己的处理策略,而不必触摸程序的代码。该软件是基于服务器的应用程序,永远不会终止。问题如下:如果用户提供了自己的插件,但其代码抛出了未处理的异常,该怎么办?这将使应用程序崩溃,服务器将脱机。鉴于插件总是创建一个从库和插件都可见的类派生的对象,显而易见的解决方案是:

class AbstractSolver
{
public:
    void solve(void)
    {
        try {
        this->solve_impl();
        } catch (...) {
            std::cout << "got exception" << std::endl;
        }
    }
private:
    virtual void solve_impl(void) = 0;
};

// This is the class of the plugin
class MySolver : public AbstractSolver
{
private:
    void solve_impl(void)
    {
        throw std::exception();
    }
}
类抽象求解器
{
公众:
无效解算(void)
{
试一试{
此->求解_impl();
}捕获(…){
标准::cout
如果用户提供了自己的插件,但其代码抛出了未经处理的异常,该怎么办?这将使应用程序崩溃,服务器将脱机

如果用户提供的插件引发插件规范不允许的异常,则这是用户提供的插件中的逻辑错误。当检测到逻辑错误时,正确的做法是立即停止执行并终止进程(可能在最后一次尝试记录故障或将即将终止通知系统中的某些其他组件之后)

您可能会问“如果用户提供了自己的插件,但其代码通过空指针执行间接寻址怎么办?”或者“如果用户提供了自己的插件,但其代码进入无限循环或导致死锁而永不返回怎么办?”逻辑错误是一种逻辑错误:当您检测到它时,您无法知道进程的状态是什么以及继续执行是否安全

如果插件不能抛出异常,则在基类中将虚拟函数声明为
noexcept
。这将要求派生类中的所有重写也为
noexcept
。如果重写无法处理异常,并且该异常在
noexcept
边界上泄漏,
std::terminate()< /代码>将被调用,终止执行。如果您需要能够在终止时重新启动服务,请考虑使用监视服务的看门狗进程。


对于异常边界中处理异常的更一般问题,考虑使用异常翻译器并将可能抛出的代码封装到lambda表达式中。我写了一篇详细的文章:

您应该(1)。在基类中将虚拟函数声明为
noexcept
,以防止派生类引发异常,或者[2]定义可能引发的异常集,然后仅捕获这些异常(并使用处理它们。不要捕获
;您不知道可能出了什么问题,也不知道系统的状态如何。我不太确定noexcept的作用,但如果我将虚拟函数声明为noexcept,则不会有任何更改。仍然会引发异常。声明
virtual
函数挂钩
noexcept
doesn不能真正解决OP的问题。如果没有
try
/
catch
块,应用程序将崩溃,因为插件抛出了未处理的异常。如果
noexcept
,应用程序将崩溃,因为插件违反了异常规范,并且运行时调用了
terminate()