日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

用_beginthreadex不用 CreateThread

發(fā)布時(shí)間:2025/3/21 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用_beginthreadex不用 CreateThread 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ?http://www.cnblogs.com/lcchuguo/p/5224576.html

在用visual studio進(jìn)行界面編程時(shí)(如MFC),前臺(tái)UI我們能夠通過MFC的消息循環(huán)機(jī)制實(shí)現(xiàn)。而對(duì)于后臺(tái)的數(shù)據(jù)處理。我們可能會(huì)用到多線程來處理。

那么對(duì)于大多數(shù)人(尤其是我這樣的菜鳥),一個(gè)比較快捷的方法便是選擇MFC多線程:AfxBeginThread或者CreateThread來進(jìn)建立多線程。當(dāng)一兩個(gè)線程還是能夠得。當(dāng)有3個(gè)或者3個(gè)以上的線程出現(xiàn)時(shí),極可能出現(xiàn)內(nèi)存泄漏。原因分析例如以下:

CWinThread的多線程不安全性:

? ? ?由于 CWinThread 會(huì)調(diào)用_beginthreadex來初始化C執(zhí)行時(shí)庫。而相同地,假設(shè)線程被強(qiáng)制終止(TerminateThread),由于 ?TerminateThread是不會(huì)去管 C執(zhí)行時(shí)庫的,從而,導(dǎo)致部分和引用計(jì)數(shù)相關(guān)的C執(zhí)行時(shí)數(shù)據(jù)的內(nèi)存釋放出現(xiàn)故障。最典型的特征是,使用STL庫的靜態(tài)變量 內(nèi)存回收將出錯(cuò),從而導(dǎo)致進(jìn)程退出時(shí)誤報(bào)異常。
此外,假設(shè)AfxBeginThread頻繁進(jìn)行回收和分配線程,假設(shè)不嚴(yán)格操作,也會(huì)導(dǎo)致崩潰。

VC6中,應(yīng)該嚴(yán)格控制STL庫的使用,避免MFC庫和STL庫并存,否則,會(huì)有非常多問題。


原因:

? ? ?AfxBeginThread在內(nèi)部直接調(diào)用了CreateThread創(chuàng)建線程而不是c語言下推薦的beginthreadex函數(shù),而這兩個(gè)函數(shù)是有差別的,主要是c執(zhí)行庫的歷史遺留問題造成的。

? ? ?在多線程環(huán)境中存在問題的C/C++執(zhí)行期庫變量和函數(shù)包含errno、_doserrno、strtok、_wcstok、strerror、_strerror、tmpnam、tmpfile、asctime、_wasctime、gmtime、_ecvt和_fcvt等。
若要使多線程C/C++程序可以正確地執(zhí)行,必須創(chuàng)建一個(gè)數(shù)據(jù)結(jié)構(gòu),并將它與使用C/C++執(zhí)行期庫函數(shù)的每一個(gè)線程關(guān)聯(lián)起來。當(dāng)你調(diào)用C?/?C?+?+執(zhí)行期庫時(shí),這些函數(shù)必須知道查看調(diào)用線程的數(shù)據(jù)塊,這樣就不會(huì)對(duì)別的線程產(chǎn)生不良影響。

那么系統(tǒng)是否知道在創(chuàng)建新線程時(shí)分配該數(shù)據(jù)塊呢?回答是它不知道。系統(tǒng)根本不知道你得到的應(yīng)用程序是用C/C++編寫的。也不知道你調(diào)用函數(shù)的線程本身是不安全的。問題在于你必須正確地進(jìn)行全部的操作。

若要?jiǎng)?chuàng)建一個(gè)新線程。絕對(duì)不要調(diào)用操作系統(tǒng)的CreateThread函數(shù)。必須調(diào)用C/C++執(zhí)行期庫函數(shù)_beginthreadex。


以下是關(guān)于_beginthreadex的一些要點(diǎn):
? ? ? 每一個(gè)線程均獲得由C/C++執(zhí)行期庫的堆棧分配的自己的tiddata內(nèi)存結(jié)構(gòu)。(tiddata結(jié)構(gòu)位于Mtdll.h文件里的Visual?C++源碼中)。傳遞給_beginthreadex的線程函數(shù)的地址保存在tiddata內(nèi)存塊中。

傳遞給該函數(shù)的參數(shù)也保存在該數(shù)據(jù)塊中。

_beginthreadex確實(shí)從內(nèi)部調(diào)用CreateThread,由于這是操作系統(tǒng)了解怎樣創(chuàng)建新線程的唯一方法。###能夠看出調(diào)用_beginthreadex時(shí)分配了額外的內(nèi)存空間。

? ? 假設(shè)調(diào)用CreateThread,而不是調(diào)用C?/?C?+?+執(zhí)行期庫的_beginthreadex來創(chuàng)建新線程,將會(huì)發(fā)生什么情況。當(dāng)一個(gè)線程調(diào)用要求tiddata結(jié)構(gòu)的C?/?C?+?+執(zhí)行期庫函數(shù)時(shí),將會(huì)發(fā)生以下的一些情況(大多數(shù)C?/?C?+?+執(zhí)行期庫函數(shù)都是線程安全函數(shù),不須要該結(jié)構(gòu))。


先。?C?/?C?+?+執(zhí)行期庫函數(shù)試圖(通過調(diào)用TlsGetValue)獲取線程的數(shù)據(jù)塊的地址。

假設(shè)返回
NULL作為tiddata塊的地址。調(diào)用線程就不擁有與該地址相關(guān)的tiddata塊。這時(shí),C?/?C?+?+執(zhí)行期庫函數(shù)就在現(xiàn)場(chǎng)為調(diào)用線程分配一個(gè)tiddata塊,并對(duì)它進(jìn)行初始化。然后該tiddata塊(通過TlsSetValue)與線程相關(guān)聯(lián)。
###_beginthreadex相相應(yīng)的推出函數(shù)是_endthreadex,這個(gè)函數(shù)會(huì)釋放tiddata的內(nèi)容。
---------------------------
? ? 假設(shè)你採用CreateThread創(chuàng)建線程。而你沒有使用上面所提到的那些特殊執(zhí)行期庫的話,也是不會(huì)出現(xiàn)故障的。假設(shè)一定要用那些執(zhí)行庫的話就最好調(diào)用_beginthreadex?這個(gè)api來創(chuàng)建線程,否則tiddata數(shù)據(jù)塊就無法撤銷,引起內(nèi)存泄漏。

你能夠參照_beginthreadex源碼來進(jìn)行理解。

總結(jié)

以上是生活随笔為你收集整理的用_beginthreadex不用 CreateThread的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。