原則49:了解new-handler的行為

本原則是針對(duì)在多線程環(huán)境下內(nèi)存中動(dòng)態(tài)存儲(chǔ)區(qū)也就是堆中空間資源的訪問而產(chǎn)生的田弥,因?yàn)槎褜儆谌中再Y源,每個(gè)線程都試圖去使用它侧巨,又因?yàn)槊總€(gè)線程是互斥地使用資源惨远,那自然就會(huì)存在一個(gè)先到先得的問題,這就是所謂的競(jìng)速孵奶。你要知道堆空間也是有限的疲酌,于是就可能出現(xiàn)當(dāng)某個(gè)線程是要使用堆空間時(shí),堆卻沒有足夠的空間提供給這個(gè)線程使用的時(shí)候了袁。這個(gè)時(shí)候你再使用new來(lái)分配空間就會(huì)失敗朗恳。雖然C++中提供了默認(rèn)的處理過程,但是有的時(shí)候你就是希望自定義整個(gè)new的過程载绿,那該如何是好粥诫?本原則就是來(lái)幫你解決這個(gè)問題的。
在這里你要知道C++是如何處理動(dòng)態(tài)內(nèi)存分配不足的問題的崭庸。以前如果遇到這種情況new會(huì)直接返回一個(gè)null怀浆,現(xiàn)在一般是返回一個(gè)bad_alloc異常。C++處理new異常通常有一個(gè)指向錯(cuò)誤處理函數(shù)的函數(shù)指針new-handler怕享,它負(fù)責(zé)對(duì)new分配不成功的處理执赡。還有一個(gè)使用這個(gè)函數(shù)指針進(jìn)行異常邏輯處理的函數(shù)叫set_new_handler,它們都在new頭文件里面函筋。
有趣的是這個(gè)set_new_handler是以new-handler為參數(shù)并以new-handler為返回值的沙合,那又是怎么回事呢?作為參數(shù)的這個(gè)new-handler是指new分配錯(cuò)誤時(shí)被調(diào)用的錯(cuò)誤處理函數(shù)驻呐,注意灌诅!這個(gè)處理函數(shù)不一定非要是系統(tǒng)的庫(kù)函數(shù),它也可以是用戶自定義的含末,不過因?yàn)閚ew-handler是一個(gè)無(wú)參數(shù)無(wú)返回值的函數(shù)的指針猜拾,所以這個(gè)錯(cuò)誤處理函數(shù)也必須是這樣的一個(gè)函數(shù)。而那個(gè)返回的new-handler指向的是set_new_handler被調(diào)用前正在被執(zhí)行的new-handler類型函數(shù)佣盒。在這里我對(duì)我自己的理解表示不確定挎袜。
這樣只要new分配不成功它就不斷地接受新的new-handler返回舊的new-handler知道new能分配成功。這樣肥惭,設(shè)計(jì)一個(gè)良好的new-handler必須做到以下幾點(diǎn):
1盯仪、讓可用內(nèi)存更多。這一點(diǎn)首先要做到有足夠的可供分配的內(nèi)存空間蜜葱,其次就是每次調(diào)用new-handler的時(shí)候就要及時(shí)釋放掉那些沒有分配成功的內(nèi)存空間全景;
2、安裝另一個(gè)new-handler牵囤。用更強(qiáng)大的new-handler替換當(dāng)前的new-handler爸黄;
3滞伟、卸載new-handler。如果沒有可用的new-handler炕贵,就將參數(shù)new-handler置為null使異常拋出梆奈;
4、拋出bad_alloc異常称开;
5亩钟、直接abort或者exit結(jié)束,啥也不做鳖轰。
對(duì)于實(shí)現(xiàn)自定義new-handler和set_new_handler清酥,作者的思想是在自定義接口中去調(diào)用這些系統(tǒng)函數(shù)來(lái)完成自定義功能,具體來(lái)說你就是在類內(nèi)實(shí)現(xiàn)就好了脆霎。在此作者給了個(gè)例子:



從上圖可見总处,主要就是在類中自定義兩個(gè)公有的static接口,這樣每個(gè)類的實(shí)例都可以使用這倆接口睛蛛。其中一個(gè)是new的重載函數(shù)鹦马,另一個(gè)是set-new-handler。它還有一個(gè)私有的static的new-handler類型的指針忆肾,用來(lái)set-new-handler被調(diào)用前正在被使用的new-handler函數(shù)荸频。這個(gè)set-new-handler所做的事情就是先把當(dāng)前正在運(yùn)行的new-handler函數(shù)保存起來(lái),然后更改currentHandler的指向?yàn)樾碌膎ew-handler客冈,最后返回那個(gè)保存起來(lái)的new-handler旭从。
這個(gè)被重載的new主要完成以下工作:
Step 1、在發(fā)生錯(cuò)誤的時(shí)候調(diào)用標(biāo)準(zhǔn)的set-new-handler场仲,這會(huì)將set-new-handler的參數(shù)置為新的global-new-handler和悦,我想這個(gè)global-new-handler是系統(tǒng)提供的new-handler吧;
Step 2渠缕、global new會(huì)被調(diào)用鸽素,我想它也就是系統(tǒng)提供的那個(gè)new吧。如果new失敗了亦鳞,那么這個(gè)new會(huì)去調(diào)用類中的new-handler馍忽,因?yàn)橛蒘tep 1可知此時(shí)的new-handler實(shí)際上是系統(tǒng)的new-handler。如果這個(gè)系統(tǒng)的new-handler還是無(wú)法解決問題燕差,它只能拋出bad-alloc異常遭笋。不過在這之前,類中的new必須把原來(lái)的系統(tǒng)的new-handler作為類中的set-new-handler的返回值來(lái)恢復(fù)系統(tǒng)的new-handler徒探。為了先前的new-handler能得到恢復(fù)瓦呼,類必須把先前的new-handler作為資源來(lái)管理;
Step 3测暗、如果系統(tǒng)的new能分配成功央串,那么類中的new就應(yīng)該返回該內(nèi)存的指針谎替,析構(gòu)函數(shù)必須把先前的new-handler恢復(fù)回去。
因?yàn)檫@個(gè)方案并不因類的不同而不同蹋辅,所以可以考慮把它做成父類的模版,讓各個(gè)子類去繼承這個(gè)特性挫掏,于是在這里作者提到了奇異遞歸模版模式侦另,簡(jiǎn)稱CRTP(Curiously Recurring Template Pattern)。它的樣子大致如下尉共。



可以看出一個(gè)父類是以子類類型來(lái)進(jìn)行特化的褒傅。
文中還提到為了支持以前在舊規(guī)范時(shí)候?qū)懗鰜?lái)的代碼,C++標(biāo)準(zhǔn)委員會(huì)提供了另一種new它在失敗時(shí)直接返回null袄友,它被稱為nothrow形式的new殿托。其使用形式如下:

這種new不好,因?yàn)樗哂芯窒扌跃珧迹荒芄茏‘?dāng)前代碼后續(xù)代碼它就管不了了支竹,所以相比之下還是拋出異常的new比較好。
總結(jié):
1鸠按、作為set-new-handler函數(shù)中的參數(shù)的new-handler允許用戶自定義礼搁,它在內(nèi)存分配不足時(shí)被調(diào)用。
2目尖、Nothrow new太局限馒吴,它只適合于一段代碼,對(duì)于后續(xù)的構(gòu)造函數(shù)什么的拋出的異常卻束手無(wú)策瑟曲。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饮戳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子洞拨,更是在濱河造成了極大的恐慌扯罐,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扣甲,死亡現(xiàn)場(chǎng)離奇詭異篮赢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)琉挖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門启泣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人示辈,你說我怎么就攤上這事寥茫。” “怎么了矾麻?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵纱耻,是天一觀的道長(zhǎng)芭梯。 經(jīng)常有香客問我,道長(zhǎng)弄喘,這世上最難降的妖魔是什么玖喘? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮蘑志,結(jié)果婚禮上累奈,老公的妹妹穿的比我還像新娘。我一直安慰自己急但,他們只是感情好澎媒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著波桩,像睡著了一般戒努。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镐躲,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天储玫,我揣著相機(jī)與錄音,去河邊找鬼萤皂。 笑死缘缚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的敌蚜。 我是一名探鬼主播桥滨,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼没佑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼橄妆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起往湿,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤纷跛,失蹤者是張志新(化名)和其女友劉穎喻括,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贫奠,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡唬血,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唤崭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拷恨。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谢肾,靈堂內(nèi)的尸體忽然破棺而出腕侄,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布冕杠,位于F島的核電站微姊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏分预。R本人自食惡果不足惜兢交,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笼痹。 院中可真熱鬧魁淳,春花似錦、人聲如沸与倡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纺座。三九已至,卻和暖如春溉潭,著一層夾襖步出監(jiān)牢的瞬間净响,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工喳瓣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留馋贤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓畏陕,卻偏偏與公主長(zhǎng)得像配乓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惠毁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,161評(píng)論 25 707
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法犹芹,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法鞠绰,繼承相關(guān)的語(yǔ)法腰埂,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,639評(píng)論 18 399
  • 閱讀目錄前言new與malloc的10點(diǎn)區(qū)別1. 申請(qǐng)的內(nèi)存所在位置2.返回類型安全性3.內(nèi)存分配失敗時(shí)的返回值4...
    yangqi916閱讀 1,987評(píng)論 0 4
  • 朦朧塵世朦朧中蜈膨,一場(chǎng)煙雨一夢(mèng)休屿笼。 原想世外花田下,朝聞鳥鳴暮水流翁巍。 奈何生身不獨(dú)有驴一,牽掛牽絆擾夢(mèng)幽。 若一世長(zhǎng)久紛...
    草木縈心閱讀 106評(píng)論 0 1
  • Hi,大家好灶壶!這是一個(gè)有關(guān)唐僧師徒四人取經(jīng)之后回家鄉(xiāng)創(chuàng)業(yè)的故事蛔趴,每篇故事都是我們團(tuán)隊(duì)成員結(jié)合當(dāng)下互聯(lián)網(wǎng)熱點(diǎn)詞匯編寫...
    硅谷堂閱讀 531評(píng)論 0 2