coinitialize()和静态混淆

时间:2012-02-29 20:18:03

标签: c++ com static

我有一个静态const类成员的情况,它调用静态函数来初始化它的值:

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

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

问题是A :: Function()有一个本地静态变量,需要通过调用CoInitialize()来初始化COM库:

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

我之前在WinMain中调用了CoInitialize():

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;
}

但是,当在对A :: Function()的调用中初始化静态成员变量A :: NUM时调用ConInitialize(),并且这将在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库的静态变量?如果我在WinMain中取消注释if语句,问题似乎就消失了,但我认为这是因为我最终调用CoInitialize()两次而CoUninitialize()只调用一次。

1 个答案:

答案 0 :(得分:0)

首先,您可以在这种情况下使用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();
    }
}

然后定义一个静态const com_scope _AppComScope。在声明之前

const int A::NUM = ...

此代码将在第一次调用A :: Function之前初始化COM环境,并在执行结束时进行清理。

极有可能你的问题是你在最终使用一些com引用之前破坏了COM环境。这解释了一旦从WinMain中删除:: CoUnitialize,问题就会消失。

P.S。

虽然这是一个坏主意,但你可能不会在主线程中调用:: CoUninitialize,因为操作系统会在你的程序完成时进行清理

P.S.S。

另外,我必须承认,应该在CPP文件中定义_AppComScope,在该文件中为A :: NUM分配值。否则,标准不保证初始化的顺序