繁体   English   中英

为什么C ++ try / catch没有捕获“纯虚拟调用”异常?

[英]Why C++ try/catch does not catch the “pure virtual call” exception?

以下函数在Microsoft Visual Studio 2017中编译。在此函数中, CAttributedObject是实现IObjectID接口的COM类。 该函数必须处理有关事件的通知。 参数pCaller是指向CAttributedObject类型的对象的指针,该对象是事件的源。 通知将通过其消息队列分派给主线程。 预计到通知到达时, pCaller指向的对象可以被销毁; 这就是代码中存在try / catch块的原因。

但是,有时,对QueryInterface的调用会引发“纯虚拟调用”异常,该异常不会被捕获并导致应用程序崩溃。 在许多其他情况下,我们使用try / catch测试对可能删除的内存的访问,并且all已经工作多年。 我不明白为什么“纯虚拟调用”异常是特殊的。

HRESULT CDataProvider::OnObjIconChanged(
            BSTR Key, BSTR Path, IUnknown* pCaller,
            UINT Flags, __int64 hIcon, const CLSID& ProviderCLSID)
{
    CAttributedObject* pAttrObj = 0;
    IObjectID* pObjID = 0;
    try {
        try { pCaller->QueryInterface(__uuidof(IObjectID), (void**)&pObjID); }
        catch(...) {}

        if (pObjID != 0)
            pAttrObj = static_cast<CAttributedObject*>(pObjID);

        if (pAttrObj != 0)
        {
            pAttrObj->SetIcon((HICON)hIcon, Flags & SHGFI_SMALLICON);
            pAttrObj->Release();
        }
    } catch(...) {}

    TreeService()->Fire_ObjIconChanged(Key, Path, hIcon);
    return S_OK;
}

我不明白为什么“纯虚拟调用”异常是特殊的。

因为它是未定义的行为,根据C ++标准。 未定义的行为,表示代码中的错误,某处。 鉴于这是未定义的行为,C ++实现可能会抛出一个可捕获的异常,但它没有义务这样做。 大多数C ++实现都会记录简短的消息,并abort()整个程序。

唯一一次可以在C ++标准的范围内进行纯虚函数调用来自抽象基类的构造函数或析构函数,并且C ++标准明确指出这是未定义的行为:

[class.abstract]

可以从抽象类的构造函数(或析构函数)调用成员函数; 对于从这样的构造函数(或析构函数)创建(或销毁)的对象,直接或间接地对纯虚函数进行虚拟调用的效果是未定义的。

没有其他可能的方法来进行纯虚函数调用,因为您无法在C ++中直接实例化抽象类(具有纯虚函数的类),这在同一子句的其他地方进一步说明。

因此,无论您转向哪种方式,最终都会出现未定义的行为。 你的代码中有一个错误,它会导致构造函数或析构函数的纯虚函数调用或内存损坏。 这必须通过捕获一些异常来解决,而是通过找到错误并修复它。

如果在这种情况下需要抛出一个可捕获的异常,它就不会是未定义的行为,不是吗?

例外不是未定义的行为。 它们的机械工作部件在C ++标准中完全定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM