在cbasevideorenderer派生类中内存损坏

Memory corrupted in CBaseVideoRenderer-derived class

本文关键字:内存 损坏 cbasevideorenderer 派生      更新时间:2023-10-16

我尝试编写一个DirectShow渲染器,能够在VS2012项目中捕获基于VIDEOINFO2的流。为此,我从Windows 7 SDK中取出基类项目,将其升级到VS2012并构建它。我的渲染器看起来像

class CapturingVideoRenderer : public CBaseVideoRenderer {
public:
    CapturingVideoRenderer(LPUNKNOWN pUnk, HRESULT *phr);
    virtual ~CapturingVideoRenderer(void);
    virtual HRESULT CheckMediaType(const CMediaType *pmt);
    virtual HRESULT DoRenderSample(IMediaSample *pMediaSample);
    virtual HRESULT SetMediaType(const CMediaType *pmt);
    virtual HRESULT StartStreaming(void);
protected:
    typedef CBaseVideoRenderer Base;
public:
    DECLARE_IUNKNOWN;

};

从实现来看,重要的部分是构造函数:

CapturingVideoRenderer::CapturingVideoRenderer(LPUNKNOWN pUnk, HRESULT *phr)
        : Base(::CLSID_CapturingVideoRenderer, Name_CapturingVideoRenderer,
        pUnk, phr) {
}

如果我现在创建一个实例(我直接这样做是为了调试),应用程序崩溃:

IBaseFilter *filter = nullptr;
CapturingVideoRenderer *renderer = nullptr;
HRESULT hr = S_OK;
obj = new CapturingVideoRenderer(nullptr, &hr);
if (FAILED(hr)) { [...] }
//hr = obj->NonDelegatingQueryInterface(IID_IBaseFilter,
//    reinterpret_cast<void **>(&filter));
hr = obj->QueryInterface(IID_IBaseFilter,
    reinterpret_cast<void **>(&filter));
if (FAILED(hr)) { [...] }

问题似乎是当执行最后一个基本函数和我的函数之间的代码时,虚函数表(或更多)以某种方式损坏。如果我直接调用NonDelegatingQueryInterface(注释掉),它可以工作(但稍后崩溃),但是对QueryInterface的调用崩溃,因为它从CUnkown基类获得实际实现,这是损坏的。

虽然我对汇编语言知之甚少,但我也逐步介绍了反汇编。在进入我的函数体之前,执行以下指令,它们覆盖基类的一部分(CUnknown的引用计数器位于rax+18h以及基类的其他字段):

000000013FCBABEF  mov         rax,qword ptr [this]
000000014000AC07  lea         rcx,[CapturingVideoRenderer::`vftable' (0140147A28h)]  
000000014000AC0E  mov         qword ptr [rax+18h],rcx 
000000013FCBAC02  mov         rax,qword ptr [this]  
000000013FCBAC0A  lea         rcx,[CapturingVideoRenderer::`vftable' (013FDF7A38h)]  
000000013FCBAC11  mov         qword ptr [rax+20h],rcx  
000000013FCBAC15  mov         rax,qword ptr [this]  

我已经运行VS2012的静态代码分析,但它没有发现任何有用的(一些错误的SAL注释在Windows SDK的基类库)。

最重要的问题当然是:我该如何解决这个问题?

我的其他问题是:在VS2012中使用DirectShow基类是否有任何已知问题?这可能吗?我必须改变一些编译器设置(atm,一切都是一样的,在项目中的可执行文件,这基本上直接来自向导-平台工具集v110和Unicode)?

似乎您无法以这种方式调试DirectShow过滤器。如果我注册它"正常",它工作得很好,所以COM似乎在这里做一些重要的事情…