我知道CreateFile返回的無效值是INVALID_HANDLE_VALUE。但是因爲我也喜歡使用RAII,所以只需將HANDLE粘貼到shared_ptr(如: shared_ptr<void> handle (CreateFile(args),&CloseHandle)
) 以確保手柄處於關閉狀態非常誘人。 我唯一關心的是如何快速簡單地執行RAII,如果CreateFile可以返回NULL作爲HANDLE值。CreateFile是否可以返回NULL?
回答
NULL
不是有效的句柄值。您可以從一些Windows API函數返回NULL
來指示失敗來辨別此事。由於處理手柄有單個功能,因此不是有效的HANDLE
值。因此CreateFile
永遠不能返回NULL
。
Raymond Chen寫了一篇關於這個話題的博客文章:Why are HANDLE return values so inconsistent?。
現在,我對shared_ptr<>
一無所知,所以不想評論你的想法是否合適。我只是回答你問的直接問題。
我不知道'NULL'可能不會返回,即使是「無效」返回值是「INVALID_HANDLE_VALUE」的函數。你確定這是嗎?你的論點是,通過這樣的'CloseHandle'可以檢測到無效句柄何時傳遞給它,無論哪個函數返回它(只要它是一個內核句柄)。但是OTOH'CloseHandle'不能**傳遞給它的無效值。 – valdo
@valdo我的觀點是'CloseHandle'不知道無效句柄是否來自CreateFile或另一個使用NULL作爲其返回值的API。另一個更簡單的說法是,如果'CreateFile'返回NULL,那麼另一個函數信號怎麼會失敗呢? –
好的,我理解你的論點,這可能是正確的。然而,理論上*這並不能證明任何事情。根據標準'CloseHandle'不需要意識到你向它傳遞了一個無效的句柄,只是在沒有任何傷害的情況下悄然失敗,例如關閉另一個(不相關的)資源。這是你的問題。您有責任檢查'CreateXXXX'的返回值,如果句柄無效,則不要調用'CloseHandle'。但是,實際上,我相信'NULL'和'INVALID_HANDLE_VALUE'都被保留爲非句柄值。 – valdo
以通用方式測試HANDLE的有效性時,請檢查NULL
和INVALID_HANDLE_VALUE
。
但是我不明白RAII與CreateFile
是否可以返回NULL
有什麼關係。您將需要提供用於測試有效性和釋放的自定義代碼,以便使HANDLE
與共享指針一起工作,因此您可以控制這些檢查,而不是共享指針類。
換句話說,無論是在共享指針還是使用正常的HANDLE
都沒有區別,檢查完全相同,並且您必須提供它們。
調用'CloseHandle'傳遞'NULL'或'INVALID_HANDLE_VALUE'實際上是很溫和的。這將是一個錯誤,但不會造成任何傷害。我承認我不會以這種方式包裝一個'HANDLE'。一個定製的RAII類課程可以很好地完成工作。我相信這已經完成了數十億次。 +1 –
@David Heffernan我很清楚,更完整的解決方案是編寫自己的句柄管理類。讓我們認爲這是朝着這個方向邁出的一步。 – Dan
至於爲什麼我關心如果CreateFile可以返回NULL以及與RAII有什麼關係。我擔心如果值爲null,shared_ptr可能不會調用自定義析構函數。在深入研究代碼時(至少對於boost來說)它看起來像它一樣。另外,如果使用返回shared_ptr的自定義創建函數,區分不包含任何內容的shared_ptr與包含null句柄的shared_ptr之間的區別將會很麻煩 – Dan
- 1. 可以String.Split()是否返回null? (.net)
- 2. AppDomain.CreateInstanceAndUnwrap是否可以返回null?
- 3. XmlSerializer.Deserialize是否可以返回null?
- 4. document.getElementsByTagName('head')[0]是否可以返回null?
- 5. C#2.0:MethodBase.GetCurrentMethod()是否可以返回null?
- 6. javax.persistence.Query.getResultList()是否可以返回null?
- 7. 是否有該函數CreateFile返回INVALID_HANDLE_VALUE和GetLastError()返回ERROR_ALREADY_EXISTS
- 8. Can WebResponse.GetResponseStream()是否返回null?
- 9. EditText.getText()是否返回null?
- 10. ExecuteScalar可以返回null嗎?
- 11. ServiceLocator.Current.GetInstance可以返回null嗎?
- 12. 可以WindowsIdentity.GetCurrent()返回null?
- 13. 當getActivity()可以返回null?
- 14. getBestProvider可以返回null嗎?
- 15. 實現IHttpHandlerFactory時GetHandler是否可以返回null?
- 16. DbProviderFactory.CreateCommandBuilder實際上是否可以返回null?
- 17. 在javascript中,NEW函數是否可以返回NULL?
- 18. 在Java中,Class.forName是否可以返回null?
- 19. 是否有可能知道BufferedReader.readLine()是否會提前返回null?
- 20. CreateFile()返回INVALID_HANDLE_VALUE,但GetLastError()是ERROR_SUCCESS
- 21. 的CreateFile()返回INVALID_HANDLE_VALUE(C++)
- 22. Powershell Receive-Job是否可以返回DataSet?
- 23. 是否可以在serviceContract中返回System.Messaging.Message?
- 24. 是否可以更改msiexec返回碼
- 25. MemberExpression是否可以返回方法
- 26. numberofRowsinSection是否可以返回NSMutableArray的VALUES?
- 27. HTTP OPTIONS請求是否可以返回204或是否總是返回200?
- 28. getChildAt(0)是否會返回null?
- 29. May UIComponent#getFamily()是否返回null?
- 30. 如何檢查它是否返回null?
請注意,當你嘗試做這樣的事情時你必須小心。請參閱:http://stackoverflow.com/questions/1562421/making-a-handle-raii-compliant-using-shared-ptr-with-a-custom-deleter – tenfour
可以爲這種資源創建RAII包裝。但是,除非你真的需要共享,否則不要使用'shared_ptr'。這是一個巨大的矯枉過正('shared_ptr'在內部爲引用計數分配一個額外的內存),再加上你不會有方便的訪問,比如直接轉換爲'HANDLE',因爲'shared_ptr'故意阻止了這個。 – valdo
優點。 unique_ptr可能是一個更好的方式去..在這個努力水平。 – Dan