coinitialize () и статическая путаница - PullRequest
0 голосов
/ 01 марта 2012

У меня есть ситуация со статическим членом класса const, который вызывает статическую функцию для инициализации его значения:

//A.h
class A
{
public:
static const int NUM;
static int Function();
};

//A.cpp
const int A::NUM = A::Function();

Проблема в том, что A :: Function () имеет локальную статическую переменную, которая требуетCOM-библиотека должна быть инициализирована с помощью вызова CoInitialize ():

//A.cpp
int A::Function()
{
static vartype m;
if(SUCCEEDED(CoInitialize(NULL)))
//Now m can be used and initialized.
// m.CreateInstance....
} 

Я ранее вызывал CoInitialize () в моем WinMain:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
if(SUCCEEDED(CoInitialize(NULL)))
    {
    MyApp* app = new MyApp;

    app->Run();

    delete app;

    CoUninitialize();
    }

return 0;
}

Но так как ConInitialize () вызывается, когдастатическая переменная-член A :: NUM инициализируется при вызове A :: Function (), и это произойдет до того, как код в WinMain выполнится, я подумал, что могу удалить его из моего WinMain:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
//if(SUCCEEDED(CoInitialize(NULL)))
    {
    MyApp* app = new MyApp;

    app->Run();

    CoUninitialize();
    }

return 0;
}

Теперь программа работает нормально, но вылетает с нарушением прав доступа при выходе.Может ли кто-нибудь пролить свет на то, почему это происходит?

РЕДАКТИРОВАТЬ: Я думаю, что поскольку статические переменные должны сохраняться в течение всей программы, когда я вызываю CoUninitialize (), локальная статическая переменная m(которая нуждается в библиотеке COM) сталкивается с проблемой.Сбой, кажется, связан с этой локальной переменной m.Но тогда возникает вопрос, когда я могу вызвать CoUninitialize () для статической переменной, которая требует библиотеки COM?Проблема, похоже, исчезнет, ​​если я раскомментирую оператор if в WinMain, но я думаю, что это потому, что я в итоге вызываю CoInitialize () дважды и CoUninitialize () только один раз.

1 Ответ

0 голосов
/ 01 марта 2012

Прежде всего, вы можете использовать RAII для этого случая. Просто определите простой класс, подобный следующему:

class com_scope
{
    com_scope(com_scope const&);
    com_scope& operator= (com_scope const&);
public:
    com_scope() 
    {
        ::CoInitialize(NULL);
    }
    com_scope(DWORD dwCo)
    {
        ::CoInitializeEx(NULL, dwCo);
    }
    virtual ~com_scope() throw()
    {
        ::CoUninitialize();
    }
}

Затем определите статический констант com_scope _AppComScope. До утверждения

const int A::NUM = ...

Этот код инициализирует среду COM перед первым вызовом A :: Function и очищает в конце выполнения.

Крайне возможно, что ваша проблема в том, что вы уничтожаете среду COM, прежде чем в конечном итоге будете использовать некоторые ссылки на com. Это объясняет тот факт, что проблема исчезает, как только вы удаляете :: CoUnitialize из WinMain.

приписка

Хотя это плохая идея, но вы не можете вызывать :: CoUninitialize в вашем основном потоке, поскольку ОС выполнит эту очистку после завершения ваших программ

P.S.S.

Кроме того, я должен признать, что следует определить _AppComScope в файле CPP, в котором вы присваиваете значение A :: NUM. В противном случае стандарт не гарантирует порядок инициализации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...