2011-11-23 133 views
5

我知道CreateFile返回的無效值是INVALID_HANDLE_VALUE。但是因爲我也喜歡使用RAII,所以只需將HANDLE粘貼到shared_ptr(如: shared_ptr<void> handle (CreateFile(args),&CloseHandle)) 以確保手柄處於關閉狀態非常誘人。 我唯一關心的是如何快速簡單地執行RAII,如果CreateFile可以返回NULL作爲HANDLE值。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',因爲'shared_ptr'故意阻止了這個。 – valdo

+0

優點。 unique_ptr可能是一個更好的方式去..在這個努力水平。 – Dan

回答

6

NULL不是有效的句柄值。您可以從一些Windows API函數返回NULL來指示失敗來辨別此事。由於處理手柄有單個功能,因此不是有效的HANDLE值。因此CreateFile永遠不能返回NULL

Raymond Chen寫了一篇關於這個話題的博客文章:Why are HANDLE return values so inconsistent?

現在,我對shared_ptr<>一無所知,所以不想評論你的想法是否合適。我只是回答你問的直接問題。

+0

我不知道'NULL'可能不會返回,即使是「無效」返回值是「INVALID_HANDLE_VALUE」的函數。你確定這是嗎?你的論點是,通過這樣的'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

但是我不明白RAII與CreateFile是否可以返回NULL有什麼關係。您將需要提供用於測試有效性和釋放的自定義代碼,以便使HANDLE與共享指針一起工作,因此您可以控制這些檢查,而不是共享指針類。

換句話說,無論是在共享指針還是使用正常的HANDLE都沒有區別,檢查完全相同,並且您必須提供它們。

+1

調用'CloseHandle'傳遞'NULL'或'INVALID_HANDLE_VALUE'實際上是很溫和的。這將是一個錯誤,但不會造成任何傷害。我承認我不會以這種方式包裝一個'HANDLE'。一個定製的RAII類課程可以很好地完成工作。我相信這已經完成了數十億次。 +1 –

+0

@David Heffernan我很清楚,更完整的解決方案是編寫自己的句柄管理類。讓我們認爲這是朝着這個方向邁出的一步。 – Dan

+0

至於爲什麼我關心如果CreateFile可以返回NULL以及與RAII有什麼關係。我擔心如果值爲null,shared_ptr可能不會調用自定義析構函數。在深入研究代碼時(至少對於boost來說)它看起來像它一樣。另外,如果使用返回shared_ptr的自定義創建函數,區分不包含任何內容的shared_ptr與包含null句柄的shared_ptr之間的區別將會很麻煩 – Dan

0

CreateFile永不返回NULL。我建議你使用已經創建的包裝ATL::CAtlFile並且不要基於shared_ptr創建一個新包裝。

+0

這就是全部很好,但可以說,我真的想在實際關閉句柄之前在我的自定義析構函數中添加測試代碼。 – Dan

+0

@Dan:那麼你可以繼承CAtlFile,並測試析構函數中的代碼。恕我直言shader_ptr爲處理看起來醜陋。 –

+0

是啊,恕我直言,Atl除了管理COM之外都是醜陋的。 – Dan

相關問題