3

我正在使用 SAPI5 API 来处理文本到语音。如果我简化我的代码看起来像这样(我删除了错误检查以尽可能简化它):

int main() {
    CoInitialize(NULL);
    CComPtr<ISpVoice> spVoice;
    spVoice.CoCreateInstance(CLSID_SpVoice);
    ...
    CoUninitialize();
    return 0;
}

由于某些奇怪的原因,如果我不调用 spVoice.Release(),我的代码就会崩溃。所以上面的代码崩溃了,但是这段代码运行良好:

int main() {
    CoInitialize(NULL);
    CComPtr<ISpVoice> spVoice;
    spVoice.CoCreateInstance(CLSID_SpVoice);
    ...
    spVoice.Release();
    CoUninitialize();
    return 0;
}

CComPtr超出范围时不会自动释放底层对象吗?

我查看了它的实现,CComPtr它确实调用Release了析构函数本身。

所以我想知道可能出了什么问题,为什么如果我打电话给Release自己,我的代码不会崩溃。但是,如果我不打电话Release,那么它就会崩溃。

4

2 回答 2

10

CComPtr 的析构函数将调用 Release。但是,当对象超出范围时,它会这样做。在上面的代码中,这只是在 main 返回之前,也就是调用 CoUninitialize 之后。

以下代码更正确,并保证析构函数在 CoUninitialize 之前运行。

int main() {
    CoInitialize(NULL);
    { // Begin scope
        CComPtr<ISpVoice> spVoice;
        spVoice.CoCreateInstance(CLSID_SpVoice);
        ...
    } / End scope, spVoice's destructor runs.
    CoUninitialize();
    return 0;
}

另一种方法是围绕 CoInitialize/CoUninitialize 创建一个 RAII 包装器。如果这个新对象在 spVoice 之前声明,它的析构函数将在 spVoice 的析构函数之后运行,从而保证正确的顺序。

于 2012-04-16T19:36:27.190 回答
-1

你是对的,你不能调用 Release。这是在析构函数中自动完成的。崩溃的一个原因可能是由于您没有在程序开始时初始化 COM 设备而发生的副作用。

于 2012-04-16T18:55:30.680 回答