在析构函数中调用Inherited IUnknown :: Release() [英] Calling Inherited IUnknown::Release() in a destructor

查看:564
本文介绍了在析构函数中调用Inherited IUnknown :: Release()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在析构函数中调用IWICImagingFactory对象上继承的IUnknown :: Release()函数会导致在对象的虚函数表(__vfptr)中显示每个条目的CXX0030:Error:expression can not be evaluate / p>

这是参考一个较早的问题,我发布,但我已经意识到,问题只发生在析构函数。虚函数表在我检查的任何其他地方都显示有效。但是,一旦在析构函数中,所有条目都显示为CXX0030错误,并尝试调用继承的IUknown :: Release()失败。



编辑:演示:

  HRESULT DemoApp :: CreateDeviceIndependentResources()
{
HRESULT hr;


hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,& mpDirect2DFactory);


if(SUCCEEDED(hr))
{
hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(& mpWICFactory)
);
}

// CoCreateInstance返回S_OK。
//这里的其他不相关的代码。
}

HRESULT DemoApp :: CreateDeviceResources()
{
HRESULT hr;
//此处用于创建设备相关资源的其他无关代码。
// mpBackgroundBitmap是一个ID2D1Bitmap *。
if(SUCCEEDED(hr))
{
hr = LoadBitmapFromFile(
mpRenderTarget,
mpWICFactory,
L.\\background.png ,
0,
0,
& mpBackgroundBitmap);
}
}


//以下LoadBitmapFromFile()代码直接从MSDN示例获取。
//我没有写它。

HRESULT DemoApp :: LoadBitmapFromFile(
ID2D1RenderTarget * pRenderTarget,
IWICImagingFactory * pIWICFactory,
PCWSTR uri,
UINT destinationWidth,
UINT destinationHeight ,
ID2D1Bitmap ** ppBitmap

{
IWICBitmapDecoder * pDecoder = NULL;
IWICBitmapFrameDecode * pSource = NULL;
IWICStream * pStream = NULL;
IWICFormatConverter * pConverter = NULL;
IWICBitmapScaler * pScaler = NULL;

HRESULT hr = pIWICFactory-> CreateDecoderFromFilename(
uri,
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
& pDecoder
);

if(SUCCEEDED(hr))
{
//创建初始框架。
hr = pDecoder-> GetFrame(0,& pSource);
}
if(SUCCEEDED(hr))
{

//将图像格式转换为32bppPBGRA
//(DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED)。
hr = pIWICFactory-> CreateFormatConverter(& pConverter);

}


if(SUCCEEDED(hr))
{
//如果指定了新的宽度或高度,
// IWICBitmapScaler并使用它来调整图像大小。
if(destinationWidth!= 0 || destinationHeight!= 0)
{
UINT originalWidth,originalHeight;
hr = pSource-> GetSize(& originalWidth,& originalHeight);
if(SUCCEEDED(hr))
{
if(destinationWidth == 0)
{
FLOAT scalar = static_cast< FLOAT>(destinationHeight)/ static_cast< FLOAT> ;(originalHeight);
destinationWidth = static_cast< UINT>(scalar * static_cast< FLOAT>(originalWidth)));
}
else if(destinationHeight == 0)
{
FLOAT scalar = static_cast< FLOAT>(destinationWidth)/ static_cast< FLOAT>(originalWidth)
destinationHeight = static_cast< UINT>(scalar * static_cast< FLOAT>(originalHeight));
}

hr = pIWICFactory-> CreateBitmapScaler(& pScaler);
if(SUCCEEDED(hr))
{
hr = pScaler->初始化(
pSource,
destinationWidth,
destinationHeight,
WICBitmapInterpolationModeCubic
);
}
if(SUCCEEDED(hr))
{
hr = pConverter->初始化(
pScaler,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone ,
NULL,
0.f,
WICBitmapPaletteTypeMedianCut
);
}
}
}
else //不缩放图像。
{
hr = pConverter->初始化(
pSource,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.f,
WICBitmapPaletteTypeMedianCut
);
}
}
if(SUCCEEDED(hr))
{

//从WIC位图创建一个Direct2D位图。
hr = pRenderTarget-> CreateBitmapFromWicBitmap(
pConverter,
NULL,
ppBitmap
);
}

SafeRelease(& pDecoder);
SafeRelease(& pSource);
SafeRelease(& pStream);
SafeRelease(& pConverter);
SafeRelease(& pScaler);

return hr;
}

//现在我在析构函数中调用SafeRelease(),虚函数表中显示错误。
DemoApp ::〜DemoApp()
{
SafeRelease(& mpDirect2DFactory);
SafeRelease(& mpWICFactory); //这里的问题显然是
SafeRelease(& mpDWriteFactory);
SafeRelease(& mpRenderTarget);
SafeRelease(& mpBackgroundBitmap);

}

// SafeRelease定义为:
template< class Interface>
inline void SafeRelease(Interface ** ppInterfaceToRelease)
{
if(* ppInterfaceToRelease!= NULL)
{
(* ppInterfaceToRelease) - &
(* ppInterfaceToRelease)= NULL;
}

}

问题是当我调用SafeRelease ()在WICFactory对象,我得到:
第一次机会异常在0x0024e135在DemoApp.exe:0xC0000005:访问冲突读取位置0x6d5c28f0。
DemoApp.exe中0x0024e135处的未处理异常:0xC0000005:访问冲突读取位置0x6d5c28f0。

解决方案

问题最近也。问题是 IWICImagingFactory 的创建和发布取决于 CoInitialize / CoUninitialize 分别被调用之前和之后。在你的应用程序中,很可能在析构函数中释放 IWICImagingFactory 之前调用 CoUninitialize()崩溃。注意, ID2D1RenderTarget 这样似乎没有受到影响,仍然可以在 CoUninitialize()后调用。 / p>

删除对 CoUninitialize()的调用RunMessageLoop()或任何地方,并将其放在析构函数中的释放调用后,崩溃应该消失。


Why does calling the inherited IUnknown::Release() function on a IWICImagingFactory object in a destructor cause a "CXX0030: Error: expression cannot be evaluated" to be shown each entry in the object's virtual function table (__vfptr)?

This is in reference to an earlier question I posted but I've since realized that the problem only occurs in the destructor. The virtual function table appears valid anywhere else I have checked. However, once in the destructor all entries are shown with the CXX0030 error and attempting to call the inherited IUknown::Release() fails.

Edit: Here is some code to demonstrate:

HRESULT DemoApp::CreateDeviceIndependentResources()
{
HRESULT hr;


hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &mpDirect2DFactory);


if (SUCCEEDED(hr))
{
    hr = CoCreateInstance(
        CLSID_WICImagingFactory,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&mpWICFactory)
        );
}

//CoCreateInstance returns S_OK.
//Other unrelated code here.
}

HRESULT DemoApp::CreateDeviceResources()
{
HRESULT hr;
//Other unrelated code here for creating device-dependant resources.
//mpBackgroundBitmap is a ID2D1Bitmap*.
    if(SUCCEEDED(hr))
    {
        hr = LoadBitmapFromFile(
            mpRenderTarget,
            mpWICFactory,
            L".\\background.png",
            0,
            0,
            &mpBackgroundBitmap);
    }
}


//The below LoadBitmapFromFile() code is taken directly from an MSDN sample.
//I didn't write it.

HRESULT DemoApp::LoadBitmapFromFile(
ID2D1RenderTarget *pRenderTarget,
IWICImagingFactory *pIWICFactory,
PCWSTR uri,
UINT destinationWidth,
UINT destinationHeight,
ID2D1Bitmap **ppBitmap
)
{
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pSource = NULL;
IWICStream *pStream = NULL;
IWICFormatConverter *pConverter = NULL;
IWICBitmapScaler *pScaler = NULL;

HRESULT hr = pIWICFactory->CreateDecoderFromFilename(
    uri,
    NULL,
    GENERIC_READ,
    WICDecodeMetadataCacheOnLoad,
    &pDecoder
    );

if (SUCCEEDED(hr))
{
    // Create the initial frame.
    hr = pDecoder->GetFrame(0, &pSource);
}
if (SUCCEEDED(hr))
{

    // Convert the image format to 32bppPBGRA
    // (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
    hr = pIWICFactory->CreateFormatConverter(&pConverter);

}


if (SUCCEEDED(hr))
{
    // If a new width or height was specified, create an
    // IWICBitmapScaler and use it to resize the image.
    if (destinationWidth != 0 || destinationHeight != 0)
    {
        UINT originalWidth, originalHeight;
        hr = pSource->GetSize(&originalWidth, &originalHeight);
        if (SUCCEEDED(hr))
        {
            if (destinationWidth == 0)
            {
                FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight);
                destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth));
            }
            else if (destinationHeight == 0)
            {
                FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth);
                destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight));
            }

            hr = pIWICFactory->CreateBitmapScaler(&pScaler);
            if (SUCCEEDED(hr))
            {
                hr = pScaler->Initialize(
                        pSource,
                        destinationWidth,
                        destinationHeight,
                        WICBitmapInterpolationModeCubic
                        );
            }
            if (SUCCEEDED(hr))
            {
                hr = pConverter->Initialize(
                    pScaler,
                    GUID_WICPixelFormat32bppPBGRA,
                    WICBitmapDitherTypeNone,
                    NULL,
                    0.f,
                    WICBitmapPaletteTypeMedianCut
                    );
            }
        }
    }
    else // Don't scale the image.
    { 
        hr = pConverter->Initialize(
            pSource,
            GUID_WICPixelFormat32bppPBGRA,
            WICBitmapDitherTypeNone,
            NULL,
            0.f,
            WICBitmapPaletteTypeMedianCut
            );
    }
}
if (SUCCEEDED(hr))
{

    // Create a Direct2D bitmap from the WIC bitmap.
    hr = pRenderTarget->CreateBitmapFromWicBitmap(
        pConverter,
        NULL,
        ppBitmap
        );
}

SafeRelease(&pDecoder);
SafeRelease(&pSource);
SafeRelease(&pStream);
SafeRelease(&pConverter);
SafeRelease(&pScaler);

return hr;
}

//Now I call SafeRelease() in my destructor and the virtual function table entires are showing the error.
DemoApp::~DemoApp()
{
SafeRelease(&mpDirect2DFactory);
SafeRelease(&mpWICFactory); //here is the problem apparently
SafeRelease(&mpDWriteFactory); 
SafeRelease(&mpRenderTarget);
SafeRelease(&mpBackgroundBitmap);

}

//SafeRelease is defined as:
template<class Interface>
inline void SafeRelease(Interface** ppInterfaceToRelease)
{
if(*ppInterfaceToRelease != NULL)
{
    (*ppInterfaceToRelease)->Release();
    (*ppInterfaceToRelease) = NULL;
        }

}

The problem is when I call SafeRelease() on the WICFactory object, I get: First-chance exception at 0x0024e135 in DemoApp.exe: 0xC0000005: Access violation reading location 0x6d5c28f0. Unhandled exception at 0x0024e135 in DemoApp.exe: 0xC0000005: Access violation reading location 0x6d5c28f0.

解决方案

I struggled with this problem lately too. The problem is that the creation and release of IWICImagingFactory depends on CoInitialize/CoUninitialize being called before and after, respectively. In your application it is likely that CoUninitialize() is called before the IWICImagingFactory is released in the destructor, which causes a crash. Note that ID2D1RenderTarget and such do not seem to be affected and can still be released after CoUninitialize() is called.

Remove the call to CoUninitialize() from RunMessageLoop() or wherever it is and put it after the release call in the destructor and the crash should go away.

这篇关于在析构函数中调用Inherited IUnknown :: Release()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆