CBasePin递增对拥有过滤器的引用。循环参考?

问题描述 投票:1回答:1

最后,我鼓起勇气尝试第一次构建DirectShow过滤器。这可能是一个愚蠢的问题,但我很困惑。

我的滤波器来自CBaseFilter,并拥有一个输出引脚,源自CBaseInputPin。输出引脚的成员引用由CComPtr智能指针保存。当构造输出引脚时,我注意到它在哑指针上存储对“所有者”过滤器的引用。对我有意义,因为我们不想创建循环引用。

但是,当CComPtr成员添加对输入引脚的引用时,将调用CBasePin::NonDelegatingAddRef()方法。

这是该方法的源代码

/* Override to increment the owning filter's reference count */

    STDMETHODIMP_(ULONG)
    CBasePin::NonDelegatingAddRef()
    {
        ASSERT(InterlockedIncrement(&m_cRef) > 0);
        return m_pFilter->AddRef();
    }

我无法理解为什么子引脚需要增加拥有过滤器的引用计数(实际创建循环引用)。

我应该在哑指针上保存所拥有的引脚的引用并删除它而不管引用计数?

c++ com directshow
1个回答
2
投票

过滤器和引脚是COM对象,但它们没有单独的生命周期。他们只有一个参考计数 - 过滤器。引脚引用和解除引用有效地递增和递减滤波器的计数器,当它达到零滤波器并且其所有引脚都被破坏时。

外部代码以通常的方式处理COM指针。在内部,许多过滤器样本显示方式,您在完成后删除引脚,例如(random pick):

//
// CSource::Destructor
//

CSource::~CSource()
{
    /*  Free our pins and pin array */
    while (m_iPins != 0) {
    // deleting the pins causes them to be removed from the array...
        delete m_paStreams[m_iPins - 1];
    }
    ASSERT(m_paStreams == NULL);
}

在大多数情况下,引脚是静态的,并在过滤器的析构函数中删除。当它们是动态的时,在移动中删除它们是不安全的,因为它们的接口指针可能会在要删除的对象上继续引用挂起的IUnknown::Release。但是,如果您只是将其保留在过滤器内部的侧面列表中,以便在过滤器销毁时推迟删除,那么这将是安全的。

此外,您不应该在过滤器内部使用由CComPtr管理的引脚。预期的方法显示在同一段代码中:newdelete用于引脚对象,并指向过滤器代码中引脚的原始指针。外部代码通过其COM接口指针与引脚通信。

© www.soinside.com 2019 - 2024. All rights reserved.