我正在使用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
那么它就会崩溃。
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 的析构函数之后运行,从而保证正确的顺序。
你是对的,你不能调用 Release。此操作在析构函数中自动完成。崩溃的一个原因可能是发生的副作用,因为您没有在程序开始时初始化 COM 公寓。