Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 未释放筛选器com对象导致崩溃_C++_Video_Com_Directshow - Fatal编程技术网

C++ 未释放筛选器com对象导致崩溃

C++ 未释放筛选器com对象导致崩溃,c++,video,com,directshow,C++,Video,Com,Directshow,我使用Viveks捕获过滤器和vlc()来模拟捕获源。当过滤器打开,我关闭vlc时,我会崩溃。堆栈跟踪表明仍然存在2个COM对象(我猜是筛选器和pin),应该在调用前释放这些对象。我的问题是我不确定在哪里释放filter和pin COM对象,我有一个fitler和pin的析构函数,但它们在vlc关闭时从未被调用。有类似问题的人() 这是dll的重要注册部分 STDAPI RegisterFilters( BOOL bRegister ) { HRESULT hr = NOERROR;

我使用Viveks捕获过滤器和vlc()来模拟捕获源。当过滤器打开,我关闭vlc时,我会崩溃。堆栈跟踪表明仍然存在2个COM对象(我猜是筛选器和pin),应该在调用前释放这些对象。我的问题是我不确定在哪里释放filter和pin COM对象,我有一个fitler和pin的析构函数,但它们在vlc关闭时从未被调用。有类似问题的人()

这是dll的重要注册部分

STDAPI RegisterFilters( BOOL bRegister )
{
    HRESULT hr = NOERROR;
    WCHAR achFileName[MAX_PATH];
    char achTemp[MAX_PATH];
    ASSERT(g_hInst != 0);

    if( 0 == GetModuleFileNameA(g_hInst, achTemp, sizeof(achTemp))) 
        return AmHresultFromWin32(GetLastError());

    MultiByteToWideChar(CP_ACP, 0L, achTemp, lstrlenA(achTemp) + 1, 
                   achFileName, NUMELMS(achFileName));

    hr = CoInitialize(0);
    if(bRegister)
    {
        hr = AMovieSetupRegisterServer(CLSID_VirtualCam, L"Virtual Cam", achFileName, L"Both", L"InprocServer32");
    }

    if( SUCCEEDED(hr) )
    {
        IFilterMapper2 *fm = 0;

        hr = CreateComObject( CLSID_FilterMapper2, IID_IFilterMapper2, fm );
        if( SUCCEEDED(hr) )
        {
            if(bRegister)
            {
                IMoniker *pMoniker = 0;
                REGFILTER2 rf2;
                rf2.dwVersion = 1;
                rf2.dwMerit = MERIT_DO_NOT_USE;
                rf2.cPins = 1;
                rf2.rgPins = &AMSPinVCam;
                hr = fm->RegisterFilter(CLSID_VirtualCam, L"Virtual Cam", &pMoniker, &CLSID_VideoInputDeviceCategory, NULL, &rf2);
            }
            else
            {
                hr = fm->UnregisterFilter(&CLSID_VideoInputDeviceCategory, 0, CLSID_VirtualCam);
            }
        }  

      // release interface
      //
      if(fm)
          fm->Release();
    }

    if( SUCCEEDED(hr) && !bRegister )
         hr = AMovieSetupUnregisterServer( CLSID_VirtualCam );

    CoFreeUnusedLibraries();
    CoUninitialize();
    return hr;
}

STDAPI DllRegisterServer()
{
    return RegisterFilters(TRUE);
}

STDAPI DllUnregisterServer()
{
    return RegisterFilters(FALSE);
}

extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{
    return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
重要的过滤部件

CVCamStream::CVCamStream(HRESULT *phr, CVCam *pParent, LPCWSTR pPinName) :
CSourceStream(NAME("Virtual Cam"),phr, pParent, pPinName), m_pParent(pParent)
{
    // Set the default media type as 320x240x24@15
    GetMediaType(4, &m_mt);
}

CVCamStream::~CVCamStream()
{
    m_pParent->Release();
} 

泄露的COM参考资料有点难以确定。假设COM客户机(在您的例子中是VLC)做的一切都是正确的(可能不是这样,但从这个假设开始是可以的),问题就出在您的代码上。它通常是以下两种情况之一:

  • 您处理的是原始指针,对于先前完成的
    AddRef
    ,没有任何匹配的
    Release
  • 有循环引用和对象保持彼此的活动状态

  • 正如您已经看到有两个对象在浮动,一个好的策略是确定它们到底是什么类,并跟踪引用计数器的更改以查看丢失的
    IUnknown::Release

    请提供一个小代码示例。我使用的是原始指针,我听说过使用CComPtr,但在我的visualstudio版本中没有得到它们。你知道我如何监控对象的引用计数吗?另外,我认为vlc做得很正确,因为我可以打开decklink捕获源并关闭它而不会出现任何错误。将调试输出跟踪放入:构造函数、析构函数、AddRef、释放方法。查看日志以获得线索。原始指针很容易出错-这是
    CComPtr
    提供帮助的地方(
    QzCComPtr
    是DirectShow基类中的备用副本,适用于没有ATL或不想使用ATL的用户)当出现崩溃或超出范围时,QzCComPtr指针会调用release吗?这些类只是几个代码屏幕,您只要看一下就知道了。离开作用域崩溃,可能会调用析构函数(因此也可能是释放),也可能不依赖于编译器设置,特别是异常处理。