共初始化()和静态混淆

coinitialize() and static confusion

本文关键字:静态 初始化      更新时间:2023-10-16

我遇到了一个静态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;
}

但是,由于ConInitialize()是在对A::Function()的调用中初始化静态成员变量A::NUM时调用的,并且这将在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;
}

现在这个程序运行得很好,但当我退出时,它会因访问违规而崩溃。有人能解释一下为什么会发生这种情况吗?

EDIT:我认为,由于静态变量应该在程序期间保持不变,所以当我调用CoUninitialize()时,本地静态变量m(需要COM库)会遇到问题。崩溃似乎与这个局部变量m有关。但问题是,我什么时候可以为需要COM库的静态变量调用CoUninitialize()?如果我在WinMain中取消注释if语句,问题似乎会消失,但我认为这是因为我最终调用了两次CoInitialize(),只调用了一次CoUninitialize()。

首先,您可以在这种情况下使用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::函数之前初始化COM环境,并在执行结束时进行清理。

您的问题极有可能是在使用某些COM引用之前破坏了COM环境。这解释了当您从WinMain中删除::CoUnitialize时,问题就会消失的事实。

p.S.

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

p.S.S.

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