C/C++執行時庫 解釋
I. CRT
CRT(C/C++ Runtime Library)是支援C/C++執行的一系列函式和程式碼的總稱。雖然沒有一個很精確的定義,但是可以知道,你的main就是它負責呼叫的,你平時呼叫的諸如strlen、strtok、time、atoi之類的函式也是它提供的。我們以Microsoft Visual.NET 2003中所附帶的CRT為例。假設你的.NET 2003安裝在C:Program FilesMicrosoft Visual Studio .NET 2003中,那麼CRT的原始碼就在C:Program FilesMicrosoft Visual Studio .NET 2003Vc7crtsrc中。既然有了這些實現的原始碼,我們就可以找到一切解釋了。
II. _beginthread/_endthread
這個函式究竟做了什麼呢?它的程式碼在thread.c中。閱讀程式碼,可以看到它最終也是通過CreateThread來建立執行緒的,主要區別在於,它先分配了一個_tiddata,並且呼叫了_initptd來初始化這個分配了的指標。而這個指標最後會被傳遞到CRT的執行緒包裝函式_threadstart中,在那裡會把這個指標作為一個TLS(Thread Local Storage)儲存起來。然後_threadstart會呼叫我們傳入的執行緒函式,並且在那個函式退出後呼叫_endthread。這裡也可以看到,_threadstart用一個__try/__except塊把我們的函式包了起來,並且在發生異常的時候,呼叫exit退出。(_threadstart和endthread的程式碼都在thread.c中)
這個_tiddata是一個什麼樣的結構呢?它在mtdll.h中定義,它的成員被很多CRT函式所用到,譬如int _terrno,這是這個執行緒中的錯誤標誌;char* _token,strtok以來這個變數記錄跨函式呼叫的資訊,...。
那麼_endthread又做了些什麼呢?除了呼叫浮點的清除程式碼以外,它還呼叫了_freeptd來釋放和這個執行緒相關的tiddata。也就是說,在_beginthread裡面分配的這塊記憶體,以及線上程執行過程中其它CRT函式中分配並且記錄在這個記憶體結構中的記憶體,在這裡被釋放了。
通過上面的程式碼,我們可以看到,如果我使用_beginthread函式建立了執行緒,它會為我建立好CRT函式需要的一切,並且最後無需我操心,就可以把清除工作做得很好,可能唯一需要注意的就是,如果需要提前終止執行緒,最好是呼叫_endthread或者是返回,而不要呼叫ExitThread,因為這可能造成記憶體釋放不完全。同時我們也可以看出,如果我們用CreateThread函式建立了執行緒,並且不對C執行庫進行呼叫(包括任何間接呼叫),就不必擔心什麼問題了。
III. CreateThread和CRT
或許有人會說,我用CreateThread建立執行緒以後,我也呼叫了C執行庫函式,並且也使用ExitThread退出了,可是我的程式執行得好好的,既沒有因為CRT沒有初始化而崩潰,也沒有因為忘記呼叫_endthread而發生記憶體洩漏,這是為什麼呢,讓我們繼續我們的CRT之旅。
假設我用CreateThread建立了一個執行緒,我呼叫strtok函式來進行字串處理,這個函式肯定是需要某些額外的執行時支援的。strtok的原始碼在strtok.c中。從程式碼可見,在多執行緒情況下,strtok的第一句有效程式碼就是_ptiddata ptd = _getptd(),它通過這個來獲得當前的ptd。可是我們並沒有通過_beginthread來建立ptd,那麼一定是_getptd搗鬼了。開啟tidtable.c,可以看到_getptd的實現,果然,它先嚐試獲得當前的ptd,如果不能,就重新建立一個,因此,後續的CRT呼叫就安全了。可是這塊ptd最終又是誰釋放的呢?開啟dllcrt0.c,可以看到一個DllMain函式。在VC中,CRT既可以作為一個動態連結庫和主程式連結,也可以作為一個靜態庫和主程式連結,這個在Project Setting->Code Generations裡面可以選。當CRT作為DLL連結到主程式時,DllMain就是CRT DLL的入口。Windows的DllMain可以由四種原因呼叫:Process Attach/Process Detach/Thread Attach/Thread Detach,最後一個,也就是當執行緒函式退出後但是執行緒還沒有銷燬前,會在這個執行緒的上下文中用Thread Detach呼叫DllMain,這裡,CRT做了一個_freeptd(NULL),也就是說,如果有ptd,就free掉。所以說,恰巧沒有發生記憶體洩漏是因為你用的是動態連結的CRT。
於是我們得出了一個更精確的結論,如果我沒有使用那些會使用_getptd的CRT函式,使用CreateThread就是安全的。
IV. 使用ptd的函式
那麼,究竟那些函式使用了_getptd呢?很多!在CRT目錄下搜尋_getptd,你會發覺很多意想不到的函式都用到了它,除了strtok、rand這類需要保持狀態的,還有所有的字串相關函式,因為它們要用到ptd中的locale資訊;所有的mbcs函式,因為它們要用到ptd中的mbcs資訊,...。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10697500/viewspace-612404/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Mac 執行 C/C++MacC++
- Microsoft Visual C++ 微軟常用執行庫合集ROSC++微軟
- C++ 多執行緒C++執行緒
- c++多執行緒C++執行緒
- c++ -- &和 * 的解釋C++
- VC多執行緒 C++ 多執行緒執行緒C++
- C++整理17_執行時多型(晚繫結)C++多型
- c++是如何執行的C++
- xmake v2.6.1 釋出,使用 Lua5.4 執行時,Rust 和 C++ 混合編譯支援RustC++編譯
- 企圖使用c++執行緒解決nodejs單執行緒問題C++執行緒NodeJS
- 簡單C++執行緒池C++執行緒
- C++使用Boost多執行緒C++執行緒
- C++簡易執行緒池C++執行緒
- C++多執行緒學習C++執行緒
- 多執行緒C++更新MYSQL執行緒C++MySql
- C++多執行緒:atomicC++執行緒
- c/c++常見關鍵字解釋C++
- MySQL 5.7從庫system lock執行緒解釋MySql執行緒
- .NET 編譯執行or解釋執行?編譯
- c++ 11 執行緒池---完全使用c++ 11新特性C++執行緒
- windows 下的C標準庫, C執行庫(CRT ,run-time), windows API 解釋. 以及linux C擴充套件WindowsAPILinux套件
- C++可以用的計算程式執行時間的方法C++
- 測試 PHP/Node.js/python/c/c++/go 語言執行時間PHPNode.jsPythonC++Go
- 【c++】c++11實現執行緒池C++執行緒
- C++多執行緒基礎教程C++執行緒
- 通過c++示例解釋回撥C++
- C++ 重解釋型別轉換C++型別
- [C++]C風格、C++風格和C++11特性的執行緒池C++執行緒
- C++建構函式解構函式的執行過程C++函式
- clion執行單個c和c++檔案(.c.cpp)C++
- 託管C++執行緒鎖實現C++執行緒
- C++ 執行緒同步的四種方式C++執行緒
- C++ 執行緒安全的單例模式C++執行緒單例模式
- c++函式模板和執行機制C++函式
- C++儲存修飾符解釋 (轉)C++
- mongodb執行計劃解釋MongoDB
- c++多執行緒程式設計:C2672C++執行緒程式設計
- C/C++—— 預設建構函式是否會執行C++函式