C++進階—> CloseHandle詳解及CloseHandle後線程未停

函數說明

BOOL CloseHandle(HANDLE hObject);
參數
hObject :代表一個已打開對象handle。
返回值
TRUE:執行成功;
FALSE:執行失敗,可以調用GetLastError()獲知失敗原因。


函數用於關閉一個內核對象。


CloseHandle到底做了什麼?

當調用CloseHandle成功後,相關的內核對象的引用計數被減1。

這個函數做的工作就這麼多。它並沒有真正的關閉內核對象,只是將計數減1,也就是說,這個時候,如果這個內核對象的引用計數不爲0的話,內核對象依然存在,如果你有辦法找到他,那麼你依然可以操作他。

一個比較常見的問題:

CreateThread後立即CloseHandle,爲什麼線程還在運行?

可以這樣認爲,CreateThread之後,線程的內核對象的引用計數爲2,CloseHandle之後,如果線程還沒有結束,那麼他的引用計數是1,不是0,此時,系統不會回收內核對象,所以線程還在執行。直到線程執行結束,引用計數變成了0,此時,系統回收。


內核對象什麼時候被刪除?

以下兩種情況,內核對象會被刪除--系統回收:

  1. 當內核對象的引用計數爲0的時候
  2. 進程結束
如果內核對象的引用計數不爲0,但是相關的進程都已經結束了,那麼該內核對象會被系統回收
參考:
進程確實沒有機會執行自己的清除操作,但是操作系統可以在進程之後進行全面的清除,使得所有操作系統資源都不會保留下來。這意味着進程使用的所有內存均被釋放,所有打開的文件全部關閉,所有內核對象的使用計數均被遞減,同時所有的用戶對象和GDI對象均被撤消。
       ----摘自Windows核心編程 第四版 4.3.3


內核對象泄露

內核對象在使用完畢之後,沒有及時調用CloseHandle關閉,在該進程運行期間,將造成內核對象泄露

內核對象泄露會對系統造成一定程度的負面影響,但進程結束退出後,操作系統會自動回收這些內核對象。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

hThread = CreateThread( NULL, 0, ThreadFunc, NULL, 0, &dwThreadId);

CloseHandle(hThread);

如上面這樣的代碼,原因爲:創建線程後返回了線程句柄,新創建的線程內核對象的使用計數是2,一個是線程本身,一個是創建線程的線程創建線程的線程closehandle後,新的線程的內核對象使用計數爲1,當這個新線程結束運行後內核對象的使用計數還要減1,這時內核對象的使用計數是0,則系統會自動刪除新線程的內核對象,這是正常的處理流程。

如果不調用CloseHandle();則新線程運行結束後,由於使用計數爲1,所以不會刪除線程內核對象,這樣就會造成內存泄漏。當然在整個程序運行結束後,操作系統會回收這些內存,因此可以知道如果不調用CloseHandle()的話,在程序運行階段會造成內存泄漏!


本文參考:

《Windows核心編程 第四版》

http://blog.csdn.net/mvtechnology/article/details/72674524


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章