標籤:get blank 多線程編程 errno 全域 lease cti log ros
在 Win32 API 中,建立線程的基本函數是 CreateThread,而 _beginthread(ex) 是C++ 運行庫的函數。為什麼要有兩個呢?因為C++ 運行庫裡面有一些函數使用了全域量,如果使用 CreateThread 的情況下使用這些C++ 運行庫的函數,就會出現不安全的問題。而 _beginthreadex 為這些全域變數做了處理,使得每個線程都有一份獨立的“全域”量。
所以,如果你的編程只調用 Win32 API/SDK ,就放心用 CreateThread;如果要用到C++ 已耗用時間庫,那麼就要使用 _beginthreadex ,並且需要在編譯環境中選擇 Use MultiThread Lib/DLL。
C++ 運行期庫有兩個建立線程的函數,另一個是 _beginthread,它們兩者的區別請自己去看MSDN:
通常他們的解釋都是這容易造成記憶體流失。這個解釋本身是沒有錯的,但是解釋得不夠完全和詳細。以至於造成很多新手盲目的信任了那句話,在那裡都是用_beginthreadex函數,或者是裝作沒有看到使用CreateThread函數。曾經有一段時間我也對這個問題很是困惑,不知道到底用那個才是對的。因為我不止一次在很多權威性的代碼中看到對CreateThread函數的直接調用。難道是權威錯了?? 抱著懷疑的態度尋找了大量的資料和書籍,終於搞明白了這個問題的關鍵所在,在此做個說明,算是對那句話的一個完善。
關於_beginthreadex和CreateThread的區別我就不做說明了,這個很容易找到的。我們只要知道一個問題:_beginthreadex是一個C執行階段程式庫的函數,CreateThread是一個系統API函數,_beginthreadex內部調用了CreateThread。只所以所有的書都強調記憶體流失的問題是因為_beginthreadex函數在建立線程的時候分配了一個堆結構並和線程本身關聯起來,我們把這個結構叫做tiddata結構,是通過執行緒區域儲存空間TLS於線程本身關聯起來。我們傳入的線程入口函數就儲存在這個結構中。tiddata的作用除了儲存線程函數入口地址之外,還有一個重要的作用就是:C執行階段程式庫中有些函數需要通過這個結構來儲存和擷取一些資料,比如說errno之類的線程全域變數。這點才是最重要的。
當一個線程調用一個要求tiddata結構的執行階段程式庫函數的時候,將發生下面的情況:
執行階段程式庫函數試圖TlsGetvalue擷取線程資料區塊的地址,如果沒有擷取到,函數就會 現場分配一個tiddata結構,並且和線程相關聯,於是問題出現了,如果不通過_endthreadex函數來終結線程的話,這個結構將不會被撤銷,記憶體流失就會出現了。但通常情況下,我們都不推薦使用_endthreadex函數來結束線程,因為裡麵包含了ExitThread調用。
找到了記憶體流失的具體原因,我們可以這樣說:只要在建立的線程裡面不使用一些要求tiddata結構的執行階段程式庫函數,我們的記憶體時安全的。所以,前面說的那句話應該這樣說才完善:
“絕對不要調用系統內建的CreateThread函數建立新的線程,而應該使用_beginthreadex,除非你線上程中絕不使用需要tiddata結構的執行階段程式庫函數”
這個需要tiddata結構的函數有點麻煩了,在侯捷的《win32多線程程式設計》一書中這樣說到:
如果在除主線程之外的任何線程中進行一下操作,你就應該使用多線程版本的C runtime library,並使用_beginthreadex和_endthreadex:
- 使用malloc()和free(),或是new和delete;
- 使用stdio.h或io.h裡面聲明的任何函數;
- 使用浮點變數或浮點運算函數;
- 調用任何一個使用了靜態緩衝區的runtime函數,比如: asctime(),strtok()或rand()等.
Addition info please refer to:
http://support.microsoft.com/kb/104641/en-us
http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx
其他一些相關文章:
_beginthreadex和CreateThread
http://blog.chinaunix.net/space.php?uid=17102734&do=blog&id=2830124
CreateThread()、_beginthread()以及_beginthreadex()聯絡與區別
http://www.cppblog.com/jans2002/archive/2011/11/21/69135.html
多線程編程之Windows環境下建立新線程