CXX0030: Ошибка: выражение не может быть оценено - PullRequest
1 голос
/ 03 октября 2011

Краткий вопрос:

Почему я вижу это в окне Locals для моего объекта IWICImagingFactory, находясь в моем деструкторе?

Длинное объяснение:

Я создаю объект IWICImagingFactory в моей функции CreateDeviceIndependentResources ():

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

Я проверил hr после этого, и это всегда S_OK.

Затем в моей функции CreateDeviceResources () я передаю указатель на объект IWICImagingFactory при вызове LoadBitmapFromFile ():

    if(SUCCEEDED(hr))
    {
        hr = LoadBitmapFromFile(
            mpRenderTarget,
            mpWICFactory,
            L".\\background.png",
            0,
            0,
            &mpBackgroundBitmap);
    }

Функция LoadBitmapFromFile точно такая же, как в примере MSDN. Вы можете увидеть большую часть кода здесь: http://msdn.microsoft.com/en-us/library/dd756686%28v=VS.85%29.aspx

Код возврата от LoadBitmapFromFile () - S_OK. Теперь у меня есть объект ID2D1Bitmap, который отлично работает.

Я не использую фабрику WIC ни для чего другого. Проблема возникает в моем деструкторе, когда я пытаюсь SafeRelease () фабрика WIC:

SafeRelease(&mpWICFactory);

SafeRelease () определяется как:

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

}

Когда в деструкторе я раскрываю объект mpWICFactory в окне Locals, я вижу ошибки «CXX0030: Ошибка: выражение не может быть оценено». На снимке экрана ниже показано окно Locals непосредственно перед вызовом SafeRelease () для объекта WICFactory.

http://img21.imageshack.us/img21/9820/localsy.jpg

Я тогда получаю ошибку: Необработанное исключение в 0x00d22395 в Program.exe: 0xC0000005: Место чтения нарушения доступа 0x6df128f0.

В чем причина этой проблемы?

РЕДАКТИРОВАТЬ: Вот полная простая программа, демонстрирующая проблему:

test.h

#ifndef TEST_H
#define TEST_H

#include <Windows.h>
#include <wincodec.h>
#include <d2d1.h>

class Test
{
public:

IWICImagingFactory *mpWICFactory;

Test();
~Test();

HRESULT Init();
};

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

}

#endif

test.cpp

#include "Test.h"

Test::Test() : mpWICFactory(NULL)
{
}

Test::~Test()
{
SafeRelease(&mpWICFactory);
}

HRESULT Test::Init()
{
   HRESULT hr = CoCreateInstance(
        CLSID_WICImagingFactory,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&mpWICFactory)
        );

   return hr;
}

main.cpp

#include <Windows.h>
#include "Test.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
               PSTR cmdLine, int showCmd)
{
if(SUCCEEDED(CoInitialize(NULL)))
{
    Test app;

    app.Init();

    CoUninitialize();
}

return 0;
}

Ответы [ 2 ]

3 голосов
/ 03 октября 2011

Короткий ответ состоит в том, что указатель виртуальной функции 0x6df128e8 недопустим, поэтому отладчик не может разыменовать его.Это то, что означает «выражение не может быть оценено».

Поэтому, когда программа чуть позже пытается вызвать одну из виртуальных функций, указатель все равно не работает, и вы получаете нарушение прав доступа.

длинная и жесткая часть, если вы точно узнаете, где ваш объект перезаписан недопустимым значением.К сожалению, это может быть где-то еще в программе ...

0 голосов
/ 04 октября 2011

Попробуйте вызвать SafeRelease() сразу после инициализации и посмотрите, работает ли он.

Кроме того, попробуйте вызвать очистку явно (с помощью некоторой функции неинициализации) вместо того, чтобы делать это в деструкторе.Когда вы оставляете очистку деструкторам, иногда вы не имеете полного контроля над тем, что именно очищается, когда.

Возможно также, что вы уничтожаете некоторые зависимые объекты в неправильном порядке.

...