问题
I'm working with SAPI5 API for processing text to speech. If I simplify my code looks like this (I removed error checking to simplify it as much as possible):
int main() {
CoInitialize(NULL);
CComPtr<ISpVoice> spVoice;
spVoice.CoCreateInstance(CLSID_SpVoice);
...
CoUninitialize();
return 0;
}
For some weird reason my code crashes if I don't call spVoice.Release(). So the code above crashes, but this code works nicely:
int main() {
CoInitialize(NULL);
CComPtr<ISpVoice> spVoice;
spVoice.CoCreateInstance(CLSID_SpVoice);
...
spVoice.Release();
CoUninitialize();
return 0;
}
Doesn't CComPtr
release the underlying object automatically as it goes out of scope?
I looked at the implementation of CComPtr
and it does call Release
in the destructor itself.
So I'm wondering what could have gone wrong and why is it that if I call Release
myself, my code doesn't crash. But if I don't call Release
then it crashes.
回答1:
CComPtr's destructor will call Release. However, it does that when the object falls out of scope. In your above code, this is just before main returns, which is after the call to CoUninitialize.
The following code is more correct, and guarantees the destructor runs prior to CoUninitialize.
int main() {
CoInitialize(NULL);
{ // Begin scope
CComPtr<ISpVoice> spVoice;
spVoice.CoCreateInstance(CLSID_SpVoice);
...
} / End scope, spVoice's destructor runs.
CoUninitialize();
return 0;
}
An alternative is to create an RAII wrapper around CoInitialize/CoUninitialize. If this new object is declared prior to spVoice, it's destructor will run after spVoice's destructor, guaranteeing correct order.
回答2:
You are right, you must NOT invoke Release. This is done automatically in the destructor. One reason of the crash might be a side effect that takes place because you don't initialize the COM appartment at the begin of your program.
来源:https://stackoverflow.com/questions/10179884/do-i-have-to-call-release-method-on-ccomptr-objects