2011-11-23 14 views
5

私はCreateFileによって返される無効な値がINVALID_HANDLE_VALUEであることを知っています。しかし、私もRAIIを使うことが好きなので、shared_ptr(このように: shared_ptr<void> handle (CreateFile(args),&CloseHandle)) にハンドルを貼り付けて、ハンドルが閉じていることを確認するのは非常に魅力的です。 RAIIを行うこの簡単で簡単な方法で私の懸念は、CreateFileがHANDLE値としてNULLを返すことができる場合です。CreateFileはNULLを返しますか?

+2

このようなことをするときは注意が必要です。参照してください:http://stackoverflow.com/questions/1562421/making-a-handle-raii-compliant-using-shared-ptr-with-a-custom-deleter – tenfour

+1

この種のリソース用のRAIIラッパーを作成しても問題ありません。しかし、あなたが本当に**共有する必要がない限り、 'shared_ptr'を使わないでください。 'shared_ptr'が故意にこれを防ぐので、' HANDLE'への直接的なキャストのような便利なアクセスはありません。 – valdo

+0

優れたポイント。 unique_ptrはおそらくこの努力のレベルで行くより良い方法でしょう。 – Dan

答えて

6

NULLは有効なハンドル値ではありません。いくつかのWindows API関数がエラーを示すためにNULLを返すという事実から、これを識別することができます。ハンドルを処分する機能は1つで、CloseHandleなので、NULLは有効なHANDLEの値ではありません。したがってCreateFileNULLを返すことはできません。

レイモンド・チェンは、このトピックに触れるブログ記事を書きました:Why are HANDLE return values so inconsistent?

今、私はshared_ptr<>について何も知らないので、あなたのアイデアが適切かどうかについてコメントをしたくありません。あなたが尋ねた直接の質問に答えるだけです。

+0

"無効な"戻り値がINVALID_HANDLE_VALUEである関数からもNULLが返されないことを知りませんでした。これは本当ですか?あなたの議論では、そのような 'CloseHandle'は、無効なハンドルが渡されたときに、(カーネルハンドルである限り)どの関数がそれを返しても検出することができます。しかし、OTOHのCloseHandleは、**無効な値を渡す**を持っていません。 – valdo

+2

@valdo私の議論は、 'CloseHandle'は、無効なハンドルがCreateFileか、戻り値として' NULL'を使う別のAPIかどうかを知らないということです。もう一つの簡単な議論は、 'CreateFile'が' NULL'を返すと、別の関数がどのようにシグナルに失敗するのか? –

+1

申し訳ありませんが、私はあなたの議論を理解しました。それはおそらく正しいでしょう。しかし、*理論的には*これは何も証明していません。標準の 'CloseHandle'によれば、無効なハンドルを渡しただけで、別の(無関係な)リソースを閉じるなど、何の害もなく黙って失敗することを認識する必要はありません。それはあなたの問題です。 'CreateXXXX'の戻り値をチェックし、ハンドルが無効な場合は' CloseHandle'を呼び出さないようにするのはあなたの責任です。しかし、実際に言えば、私は 'NULL'と' INVALID_HANDLE_VALUE'の両方が非ハンドル値として予約されていると思います。 – valdo

1

一般的な方法でHANDLEの妥当性をテストする場合は、NULLINVALID_HANDLE_VALUEの両方を確認してください。

しかし、がNULLを返すことができるかどうかは、RAIIと関係がありません。 HANDLEを共有ポインタで動作させるためには、有効性のテストと割り当て解除のカスタムコードを提供する必要があります。共有ポインタクラスではなく、これらのチェックを制御します。

言い換えれば、共有ポインタにあるかどうかに違いはありません。通常はHANDLEです。チェックはまったく同じで、いずれかの方法で指定する必要があります。

+1

実際には 'NULL'か' INVALID_HANDLE_VALUE'を渡して 'CloseHandle'を呼び出すのはかなり害です。それは間違いですが、これには害はありません。私はこのように「ハンドル」を包んでいないと認めます。別注のRAIIクラスは仕事をうまくやってくれるでしょう。私はそれが何十倍もの出来事が終わったと確信しています。 +1 –

+0

@David Heffernan私は、より完全な解決策があなた自身のハンドル管理クラスを書くことであることをよく知っています。これをその方向の一歩と考えてみましょう。 – Dan

+0

なぜ私は、CreateFileがNULLを返すことができ、RAIIと何が関係があるかを気にします。値がnullの場合、shared_ptrがカスタムデストラクタを呼び出さない可能性があります。(少なくともブーストのために)コードを深く見れば、それはとにかくやっているように見えます。また、shared_ptrを返すカスタム作成関数を使用する場合、nullハンドルを含むものと何も含まないshared_ptrを区別するのは面倒です – Dan

0

CreateFileは決してNULLを返しません。すでに作成されたラッパーATL::CAtlFileを使用し、shared_ptrに基づいて新しいラッパーを作成しないことをお勧めします。

+0

私は実際にハンドルを閉じる前に私のカスタムデストラクタでテストコードを追加したかったと言うことができます。 – Dan

+0

@ダン:さて、あなたはCAtlFileを継承し、デストラクタでコードをテストできます。ハンドルのためのIMHO shader_ptrは醜いです。 –

+0

ええええええええええええええんは、COMを管理すること以外何も醜いです。 – Dan

関連する問題