亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

CreateThread()與beginthread()的區別詳細解析

2020-01-26 15:51:18
字體:
來源:轉載
供稿:網友

我們知道在Windows下創建一個線程的方法有兩種,一種就是調用Windows API CreateThread()來創建線程;另外一種就是調用MSVC CRT的函數_beginthread()或_beginthreadex()來創建線程。相應的退出線程也有兩個函數Windows API的ExitThread()和CRT的_endthread()。這兩套函數都是用來創建和退出線程的,它們有什么區別呢?

很多開發者不清楚這兩者之間的關系,他們隨意選一個函數來用,發現也沒有什么大問題,于是就忙于解決更為緊迫的任務去了,而沒有對它們進行深究。等到有一天忽然發現一個程序運行時間很長的時候會有細微的內存泄露,開發者絕對不會想到是因為這兩套函數用混的結果。

根據Windows API和MSVC CRT的關系,可以看出來_beginthread()是對CreateThread()的包裝,它最終還是調用CreateThread()來創建線程。那么在_beginthread()調用CreateThread()之前做了什么呢?我們可以看一下_beginthread()的源代碼,它位于CRT源代碼中的thread.c。我們可以發現它在調用CreateThread()之前申請了一個叫_tiddata的結構,然后將這個結構用_initptd()函數初始化之后傳遞給_beginthread()自己的線程入口函數_threadstart。_threadstart首先把由_beginthread()傳過來的_tiddata結構指針保存到線程的顯式TLS數組,然后它調用用戶的線程入口真正開始線程。在用戶線程結束之后,_threadstart()函數調用_endthread()結束線程。并且_threadstart還用__try/__except將用戶線程入口函數包起來,用于捕獲所有未處理的信號,并且將這些信號交給CRT處理。

所以除了信號之外,很明顯CRT包裝Windows API線程接口的最主要目的就是那個_tiddata。這個線程私有的結構里面保存的是什么呢?我們可以從mtdll.h中找到它的定義,它里面保存的是諸如線程ID、線程句柄、erron、strtok()的前一次調用位置、rand()函數的種子、異常處理等與CRT有關的而且是線程私有的信息??梢奙SVC CRT并沒有使用我們前面所說的__declspec(thread)這種方式來定義線程私有變量,從而防止庫函數在多線程下失效,而是采用在堆上申請一個_tiddata結構,把線程私有變量放在結構內部,由顯式TLS保存_tiddata的指針。

了解了這些信息以后,我們應該會想到一個問題,那就是如果我們用CreateThread()創建一個線程然后調用CRT的strtok()函數,按理說應該會出錯,因為strtok()所需要的_tiddata并不存在,可是我們好像從來沒碰到過這樣的問題。查看strtok()函數就會發現,當一開始調用_getptd()去得到線程的_tiddata結構時,這個函數如果發現線程沒有申請_tiddata結構,它就會申請這個結構并且負責初始化。于是無論我們調用哪個函數創建線程,都可以安全調用所有需要_tiddata的函數,因為一旦這個結構不存在,它就會被創建出來。

那么_tiddata在什么時候會被釋放呢?ExitThread()肯定不會,因為它根本不知道有_tiddata這樣一個結構存在,那么很明顯是_endthread()釋放的,這也正是CRT的做法。不過我們很多時候會發現,即使使用CreateThread()和ExitThread() (不調用ExitThread()直接退出線程函數的效果相同),也不會發現任何內存泄露,這又是為什么呢?經過仔細檢查之后,我們發現原來密碼在CRT DLL的入口函數DllMain中。我們知道,當一個進程/線程開始或退出的時候,每個DLL的DllMain都會被調用一次,于是動態鏈接版的CRT就有機會在DllMain中釋放線程的_tiddata。可是DllMain只有當CRT是動態鏈接版的時候才起作用,靜態鏈接CRT是沒有DllMain的!這就是造成使用CreateThread()會導致內存泄露的一種情況,在這種情況下,_tiddata在線程結束時無法釋放,造成了泄露。

我們可以用下面這個小程序來測試:

復制代碼 代碼如下:

#include <Windows.h>
#include <process.h>
void thread(void *a)
{
    char* r = strtok( "aaa", "b" );
    ExitThread(0); // 這個函數是否調用都無所謂
}
int main(int argc, char* argv[])
{
    while(1) {
        CreateThread(  0, 0, (LPTHREAD_START_ROUTINE)thread, 0, 0, 0 );
        Sleep( 5 );
    }
return 0;
}

如果用動態鏈接的CRT (/MD,/MDd)就不會有問題,但是,如果使用靜態鏈接CRT (/MT,/MTd),運行程序后在進程管理器中觀察它就會發現內存用量不停地上升,但是如果我們把thread()函數中的ExitThread()改成_endthread()就不會有問題,因為_endthread()會將_tiddata()釋放。

這個問題可以總結為:當使用CRT時(基本上所有的程序都使用CRT),請盡量使用_beginthread()/_beginthreadex()/_endthread()/_endthreadex()這組函數來創建線程。在MFC中,還有一組類似的函數是AfxBeginThread()和AfxEndThread(),根據上面的原理類推,它是MFC層面的線程包裝函數,它們會維護線程與MFC相關的結構,當我們使用MFC類庫時,盡量使用它提供的線程包裝函數以保證程序運行正確。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
青草青草久热精品视频在线网站| 日韩精品亚洲精品| 国产欧美久久一区二区| 久久久精品亚洲| 美女视频久久黄| 亚洲精品久久久久中文字幕二区| 欧美激情网友自拍| 国产亚洲精品久久久久动| 久久久久久久激情视频| 成人免费淫片aa视频免费| 欧美第一黄网免费网站| 日韩精品免费在线视频| 国产精品海角社区在线观看| 欧美三级免费观看| 91沈先生在线观看| 日韩av成人在线| 亚洲欧美国产日韩天堂区| 久久久久国产精品免费| 欧美日韩亚洲成人| 欧美中文字幕在线观看| 97国产精品视频| 清纯唯美亚洲综合| 91精品国产综合久久久久久久久| 8x海外华人永久免费日韩内陆视频| 成人精品aaaa网站| 免费av在线一区| 精品国产视频在线| 欧美激情在线狂野欧美精品| 国产精品国产自产拍高清av水多| 久久久久久成人| 亚洲一区二区三区成人在线视频精品| 中文字幕精品网| 正在播放欧美视频| 国产亚洲精品久久久久久777| 日韩精品在线观看网站| 久久视频精品在线| 国产成人自拍视频在线观看| 日韩精品高清视频| 成人欧美一区二区三区在线| 欧美尺度大的性做爰视频| 国产欧美一区二区三区久久人妖| 久久中文字幕在线| 久久久999精品| 亚洲国产美女精品久久久久∴| 久久久国产成人精品| 欧美日韩爱爱视频| 亚洲白拍色综合图区| 午夜精品久久久久久久久久久久| 久久综合久中文字幕青草| 国产女人精品视频| 日韩成人在线视频| 91精品国产高清久久久久久91| 日本高清视频一区| 国产精品99久久久久久白浆小说| 色婷婷**av毛片一区| 欧美色视频日本高清在线观看| 亚洲国产欧美一区二区三区久久| 久久国产天堂福利天堂| 国产精品久久久久久亚洲影视| 亚洲精品wwwww| 久久久之久亚州精品露出| 琪琪亚洲精品午夜在线| 日韩在线视频网| 上原亚衣av一区二区三区| 欧美国产在线电影| 91精品久久久久久久久不口人| 91国在线精品国内播放| 成人精品在线观看| 色播久久人人爽人人爽人人片视av| 亚洲精品国偷自产在线99热| 韩日欧美一区二区| 国产成人福利夜色影视| 久久影院免费观看| 性欧美暴力猛交69hd| 人九九综合九九宗合| 中日韩午夜理伦电影免费| 亚洲在线一区二区| 亚洲日韩中文字幕在线播放| 奇门遁甲1982国语版免费观看高清| 欧美在线视频观看| 欧美极品少妇xxxxⅹ裸体艺术| 在线亚洲男人天堂| 久久久国产精品一区| 国产不卡精品视男人的天堂| 亚洲天堂男人天堂| 欧美日韩福利在线观看| 亚洲精品自拍视频| 亚洲一品av免费观看| 精品久久久久国产| 亚洲精品91美女久久久久久久| 亚洲福利在线观看| 国产一区二区三区高清在线观看| 久久av在线播放| 亚洲欧美日韩视频一区| 2019最新中文字幕| 91人人爽人人爽人人精88v| 全球成人中文在线| 性色av一区二区三区红粉影视| 欧美一级成年大片在线观看| 亚洲小视频在线观看| 麻豆一区二区在线观看| 欧美在线性爱视频| 高清亚洲成在人网站天堂| 97av在线视频免费播放| 国产精品久久久久免费a∨| 欧美精品在线视频观看| 国产午夜精品视频免费不卡69堂| 奇门遁甲1982国语版免费观看高清| 亚洲欧美日韩网| 成人性教育视频在线观看| 成人国产精品免费视频| 国产精品久久中文| 欧美又大粗又爽又黄大片视频| 日韩精品中文字幕在线播放| 国产精品视频专区| 亚洲国产精品99久久| 久久久成人精品视频| 亚洲精品视频免费在线观看| 欧美体内谢she精2性欧美| 福利微拍一区二区| 亚洲一区亚洲二区亚洲三区| 国产精品久久久久久久久久免费| 精品福利樱桃av导航| 欧洲中文字幕国产精品| 国产欧美一区二区三区久久| 久久视频国产精品免费视频在线| 亚洲日本成人女熟在线观看| 色七七影院综合| 亚洲国产精品999| 中文字幕久久久av一区| 国产va免费精品高清在线观看| 国产视频丨精品|在线观看| 久久精品99久久香蕉国产色戒| 久久香蕉频线观| 亚洲一区二区免费在线| 国产一区二区在线免费| 欧美在线精品免播放器视频| 国产69精品久久久久9| 欧美性受xxxx白人性爽| 成人国产精品av| 日韩av资源在线播放| 国产精品一区二区久久国产| 国产精品中文字幕久久久| 欧美激情区在线播放| 久久在精品线影院精品国产| 日韩精品福利网站| 91免费综合在线| 国产成人啪精品视频免费网| 日韩中文字幕第一页| 国产成人在线一区| 成人黄色短视频在线观看| 成人写真视频福利网| 国产在线播放不卡| 欧美激情国产日韩精品一区18| 青青草原成人在线视频| 国产精品极品美女在线观看免费| 91在线国产电影| 日本久久久久久久| 亚洲永久在线观看| 亚洲欧美成人网| 欧美精品情趣视频| 亚洲国产日韩一区| 秋霞成人午夜鲁丝一区二区三区| 久久精品中文字幕|