【问题标题】:Do I have to call Release() method on CComPtr objects?我必须在 CComPtr 对象上调用 Release() 方法吗?
【发布时间】:2012-04-28 02:56:56
【问题描述】:

我正在使用 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,它就会崩溃。

【问题讨论】:

  • 一般来说,未释放的指针不会崩溃,只会造成内存泄漏。您创建的 sn-p 是否与您的完整程序一样?
  • @MarkRansom 我将崩溃范围缩小到调用spVoice.Release()。我可以尝试创建一个有效的 sn-p 并继续添加内容,直到它崩溃。

标签: windows com atl smart-pointers sapi


【解决方案1】:

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 的析构函数之后运行,保证正确的顺序。

【讨论】:

  • 我在 CoInitialize/CoUninitialize 周围使用了 RAII 包装器,它不再崩溃。感谢所有帮助过我的人!
  • 为什么如果你在 ::CoUninitialize() 之后调用 Release() 会导致崩溃?
【解决方案2】:

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

【讨论】:

  • 对象在析构函数中被释放,但是you need to know when your destructors run.
  • @mox,对不起,我确实初始化了 COM。我忘了在代码 sn-p 中提到这一点,因为我想让它尽可能短。
  • @RaymondChen 感谢您链接到文章。我现在就读。
  • @RaymondChen 一定是这样!我的结构与您在CoUninitialize 示例中显示的结构完全相同。我现在正在重构代码以确保spVoiceCoUninitialize 被调用之前被销毁。 (PS。我还更新了问题中的代码示例。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
相关资源
最近更新 更多