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 を呼び出してはいけません。これはデストラクタで自動的に行われます。クラッシュの原因の 1 つは、プログラムの開始時に COM アパートメントを初期化していないために発生する副作用である可能性があります。

于 2012-04-16T18:55:30.680 に答える