CComPtrのRleaseメソッドとDetachメソッドの違いについて

解決


キキ  2009-07-15 11:08:05  No: 70591  IP: [192.*.*.*]

CComPtr<hoge> h;
for (int i = 0; i < max; i++)
{
    h.Relase();
    ret = dosomething(&h);
    h->hogehoge();
}

CComPtr<hoge> h;
for (int i = 0; i < max; i++)
{
    h.Detach();
    ret = dosomething(&h);
    h->hogehoge();
}

・RleaseメソッドよりDetachメソッドを使用したほうがパフォーマンスがよいか?
・パフォーマンスがいいのならDetachメソッドを使用するが、Detachメソッドを使用した場合メモリリークは起きていないか

この2つがわからないんでが知っている方がいたら教えてくださいませんか?

編集 削除
...  2009-07-15 12:26:09  No: 70592  IP: [192.*.*.*]

>・RleaseメソッドよりDetachメソッドを使用したほうがパフォーマンスがよいか?
>Detachメソッドを使用した場合メモリリークは起きていないか
自分でやってみればいいのに。

編集 削除
aetos  2009-07-15 12:27:56  No: 70593  IP: [192.*.*.*]

用途が違うので、パフォーマンスだけを根拠にどっちを使うか決めるものではありません。

> Detachメソッドを使用した場合メモリリークは起きていないか

Release すべきところで Detach を使えば起きる可能性はあります。

編集 削除
 2009-07-15 13:05:19  No: 70594  IP: [192.*.*.*]

DetachはReleaseせずにスマートポインターからCOMインスタンスを切り離したいときに使うもの

編集 削除
subaru  2009-07-15 13:07:14  No: 70595  IP: [192.*.*.*]

Release にしても Detach にしても呼んだ後は
もうそのインスタンスは使っちゃいけないと思うのだけど
ちゃんと動きますか?

編集 削除
キキ  2009-07-15 13:24:02  No: 70596  IP: [192.*.*.*]

皆さん回答ありがとうございます

>...さん
パフォーマンスに関しては自分で調べれますね。反省します
メモリリークの調べ方ってあるのですか?

>aetosさん
>Release すべきところで Detach を使えば起きる可能性はあります。
この状況がわからないのです…。

>あさん
>DetachはReleaseせずにスマートポインターからCOMインスタンスを切り離したいときに使うもの
スマートポインタから切り離したら、誰が解放するのか?が気になりまして。
だからメモリリークを起こすのかなと思ったんですけど。間違っていますかね?
MSDNをみたらDetachメソッドはポインタの所有権を解放します。
Releaseメソッドはインターフェイスを解放します。
この違いもわかりません。

>subaruさん
問題なく動いてます。

編集 削除
aetos  2009-07-15 13:43:16  No: 70597  IP: [192.*.*.*]

> スマートポインタから切り離したら、誰が解放するのか?が気になりまして。

プログラマがしなければ誰もしません。

> MSDNをみたらDetachメソッドはポインタの所有権を解放します。
> Releaseメソッドはインターフェイスを解放します。
> この違いもわかりません。

まず、所有者(所有権)とは何かを考えます。
所有者とは、この場合、CComPtr が保持している生ポインタが指すインターフェイスを開放する者のことです。生ポインタに対して IUnknown::Release を呼ぶ者と言い換えてもよいです。
CComPtr はインターフェイス ポインタに対する所有権を持っています。これは、CComPtr がデストラクトされる際に、その生ポインタを開放するということです。
これは Release と同じことです。

Detach は所有権を放棄します。
つまり、デストラクタで生ポインタを開放しなくなります。結果、CComPtr のデストラクト後も生ポインタは有効なままです。

CComPtr のデストラクト後も生ポインタが有効である必要がある場合には Detach を使います。かつ、その場合は別途 IUnknown::Release を呼ぶ必要があります。
もうそのポインタを使用しない場合には Release を呼びます。

> 自分でやってみればいいのに。

やってみてもメモリリークはなかなか確認しづらいと思います。

> ちゃんと動きますか?

メモリリークを無視すれば動きます。
CComPtr::operator & は、CComPtr が生ポインタを保持していない場合に、新しいポインタ(の所有権)を獲得するためのものです(Attach と同じです)。
ですから、dosomething は hoge にアクセスする関数ではなく、新しい hoge インスタンスを作る関数と思われます。
そのため、開放後の &h を dosomething に渡すのはまったく正当です。

編集 削除
aetos  2009-07-15 13:44:13  No: 70598  IP: [192.*.*.*]

> 問題なく動いてます。

「問題なく動いている」と「問題なく動いているように見える」は違います。
今回のケースで Detach を使っていれば、短期的には問題なく動いているように見えても、いずれメモリを食いつぶします。

編集 削除
 2009-07-15 14:11:23  No: 70599  IP: [192.*.*.*]

そのための戻り値

編集 削除
キキ  2009-07-15 14:50:43  No: 70600  IP: [192.*.*.*]

皆さん回答ありがとうございます

DetachとRelaseの違いがわかりました。
ポインタを解放する必要があるのでReleaseを使用します

ところで…。ループ内でRelaseするんだったらループ内で宣言するのと
同じですよね?

CComPtr<hoge> h;
for (int i = 0; i < max; i++)
{
    h.Relase();
    ret = dosomething(&h);
    h->hogehoge();
}

よりも
for (int i = 0; i < max; i++)
{
    CComPtr<hoge> h;
    ret = dosomething(&h);
    h->hogehoge();
}
のコードのほうがすっきりしますよね。

編集 削除
subaru  2009-07-15 15:45:53  No: 70601  IP: [192.*.*.*]

ああ、インスタンスを使いまわしたいというわけか。
好みの問題もあるけど後者のコードの方がわかりやすいかも。

編集 削除
aetos  2009-07-15 15:52:15  No: 70602  IP: [192.*.*.*]

> のコードのほうがすっきりしますよね。

そうですね。
この場合は CComPtr がデストラクトされる際に Release を呼びますから、明示的に Release する必要がありません。そのためのスマートポインタですしね。
若干パフォーマンスが悪くなる気がします(自信なし)が、スマートポインタはごく小さなオブジェクトなので劣化も微々たるものだと思います。それなら読みやすい方がメリットがあるでしょうね。

編集 削除
キキ  2009-07-15 19:20:08  No: 70603  IP: [192.*.*.*]

皆さん最後まで回答してくれてありがとうございます
とても助かりました。
また質問した時にはよろしくお願いします

編集 削除