關於CreateThread和_beginthreadex的區別與聯繫



1.簡單來說CreateThread是Windows下用於創建線程的系統API,_beginthreadex則是Visual C++運行時庫函數

2._beginthreadex會在內存堆上分配一個與線程相關的數據塊,而CreateThread不會分配該數據塊

3.如果調用strtok、strerror、gmtime等等,會分配線程相關的數據塊。當線程退出時,用_beginthreadex創建的線程會調用_exitthreadex釋放該數據塊;相反用CreateThread創建的線程並不會調用_exitthreadex,從而導致內存泄露。

具體可以調試到VC++給定的源碼進行深入理解。上面提到的數據塊,其實就是Windows的線程本地存儲器(TLS)的運用。


由於我們在編寫C/C++程序時,會調用第3點中涉及到的運行時庫函數,所以建議在創建線程的時候不要直接調用CreateThread函數,而是調用_beginthreadex來創建線程。

至於兩者的聯繫,_beginthreadex會調用CreateThread來創建線程實例。

同時最好不會調用_beginthread來創建線程,因爲_beginthread參數太少,不能全面設置線程的一些信息。

例如,如果使用_beginthread,就無法創建帶有安全屬性的新線程,無法創建暫停的線程,也無法獲得線程的I D值。_endthread函數的情況與之類似。它不帶參數,這意味着線程的退出代碼必須硬編碼爲0。

_endthread函數還存在另一個很難注意到的大問題。在_endthread調用ExitThread之前,它調用CloseHandle。

DWORD dwExitCode;  
HANDLE handle = _beginthread(...);  
GetExitCodeThread(handle, &dwExitCode);  
CloseHandle(handle);  
新創建的線程可以在第一個線程調用GetExitCodeThread之前運行、返回和終止。如果出現這種情況,handle中的值將無效,因爲_endthread已經關閉了新線程的句柄。不用說,由於相同的原因,對CloseHandle的調用也將失敗。

新的_endthreadex函數並不關閉線程的句柄,因此,如果用調用_beginthreadex來取代調用_beginthread,那麼上面的代碼段將能正確運行。記住,當線程函數返回時, _beginthreadex調用_endthreadex,而_beginthread,則調用_endthread。

發佈了7 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章