C++基礎(chǔ)問題(二)

1.malloc的原理埂陆,另外brk系統(tǒng)調(diào)用和mmap系統(tǒng)調(diào)用的作用

Malloc函數(shù)用于動(dòng)態(tài)分配內(nèi)存敲茄。為了減少內(nèi)存碎片和系統(tǒng)調(diào)用的開銷,malloc其采用內(nèi)存池的方式娃善,先申請(qǐng)大塊內(nèi)存作為堆區(qū),然后將堆區(qū)分為多個(gè)內(nèi)存塊瑞佩,以塊作為內(nèi)存管理的基本單位会放。當(dāng)用戶申請(qǐng)內(nèi)存時(shí),直接從堆區(qū)分配一塊合適的空閑塊钉凌。Malloc采用隱式鏈表結(jié)構(gòu)將堆區(qū)分成連續(xù)的咧最、大小不一的塊,包含已分配塊和未分配塊御雕;同時(shí)malloc采用顯示鏈表結(jié)構(gòu)來管理所有的空閑塊矢沿,即使用一個(gè)雙向鏈表將空閑塊連接起來,每一個(gè)空閑塊記錄了一個(gè)連續(xù)的酸纲、未分配的地址捣鲸。
當(dāng)進(jìn)行內(nèi)存分配時(shí),Malloc會(huì)通過隱式鏈表遍歷所有的空閑塊闽坡,選擇滿足要求的塊進(jìn)行分配栽惶;當(dāng)進(jìn)行內(nèi)存合并時(shí),malloc采用邊界標(biāo)記法疾嗅,根據(jù)每個(gè)塊的前后塊是否已經(jīng)分配來決定是否進(jìn)行塊合并外厂。

Malloc在申請(qǐng)內(nèi)存時(shí),一般會(huì)通過brk或者mmap系統(tǒng)調(diào)用進(jìn)行申請(qǐng)代承。其中當(dāng)申請(qǐng)內(nèi)存小于128K時(shí)汁蝶,會(huì)使用系統(tǒng)函數(shù)brk在堆區(qū)中分配;而當(dāng)申請(qǐng)內(nèi)存大于128K時(shí)论悴,會(huì)使用系統(tǒng)函數(shù)mmap在映射區(qū)分配掖棉。

2.C++的內(nèi)存管理

在C++中,虛擬內(nèi)存分為代碼段膀估、數(shù)據(jù)段幔亥、BSS段、堆區(qū)察纯、文件映射區(qū)以及棧區(qū)六部分帕棉。
代碼段:包括只讀存儲(chǔ)區(qū)和文本區(qū),其中只讀存儲(chǔ)區(qū)存儲(chǔ)字符串常量捐寥,文本區(qū)存儲(chǔ)程序的機(jī)器代碼笤昨。
數(shù)據(jù)段:存儲(chǔ)程序中已初始化的全局變量和靜態(tài)變量
bss 段:存儲(chǔ)未初始化的全局變量和靜態(tài)變量(局部+全局)祖驱,以及所有被初始化為0的全局變量和靜態(tài)變量握恳。
堆區(qū):調(diào)用new/malloc函數(shù)時(shí)在堆區(qū)動(dòng)態(tài)分配內(nèi)存,同時(shí)需要調(diào)用delete/free來手動(dòng)釋放申請(qǐng)的內(nèi)存捺僻。
映射區(qū):存儲(chǔ)動(dòng)態(tài)鏈接庫以及調(diào)用mmap函數(shù)進(jìn)行的文件映射
:使用椣缤荩空間存儲(chǔ)函數(shù)的返回地址崇裁、參數(shù)、局部變量束昵、返回值

地址示意圖

3.段錯(cuò)誤發(fā)生原因

段錯(cuò)誤通常發(fā)生在訪問非法內(nèi)存地址的時(shí)候拔稳,具體來說分為以下幾種情況:
MMU在做邏輯地址到物理地址的轉(zhuǎn)換時(shí)發(fā)生2次檢查
一,檢查邏輯地址是否在某個(gè)已定義的內(nèi)存映射區(qū)域锹雏,這一步通過和mm_struct中巴比,mmap指針?biāo)涗浀膙m_area_struct鏈表中的每個(gè)每個(gè)節(jié)點(diǎn)所限定的虛擬內(nèi)存區(qū)域比較 實(shí)現(xiàn)。vm_area_struct結(jié)構(gòu)中的vm_start和vm_end成員記錄該節(jié)點(diǎn)所定義的虛擬內(nèi)存區(qū)域的起始/結(jié)束地址(邏輯地址)礁遵。如果要訪問的地址不在任何一個(gè)區(qū)域中轻绞,則說明是一個(gè)非法的地址。Linux在搜索vm_area_struct是佣耐,不是使用鏈表政勃,而是使用樹結(jié)構(gòu)加速查找速度。
二兼砖,MMU得到該地址的頁表項(xiàng)奸远,檢查頁表項(xiàng)中的權(quán)限信息,如果操作(讀/寫)與權(quán)限不符讽挟,則觸發(fā)保護(hù)異常懒叛。

簡(jiǎn)言之:使用野指針,試圖修改字符串常量的內(nèi)容

4.內(nèi)存泄漏

內(nèi)存泄漏(memory leak)是指由于疏忽或錯(cuò)誤造成了程序未能釋放掉不再使用的內(nèi)存的情況耽梅。內(nèi)存泄漏并非指內(nèi)存在物理上的消失芍瑞,而是應(yīng)用程序分配某段內(nèi)存后,由于設(shè)計(jì)錯(cuò)誤褐墅,失去了對(duì)該段內(nèi)存的控制拆檬,因而造成了內(nèi)存的浪費(fèi)。
內(nèi)存泄漏的分類:

  1. 堆內(nèi)存泄漏 (Heap leak)妥凳。對(duì)內(nèi)存指的是程序運(yùn)行中根據(jù)需要分配通過malloc,realloc new等從堆中分配的一塊內(nèi)存竟贯,再是完成后必須通過調(diào)用對(duì)應(yīng)的 free或者delete 刪掉。如果程序的設(shè)計(jì)的錯(cuò)誤導(dǎo)致這部分內(nèi)存沒有被釋放逝钥,那么此后這塊內(nèi)存將不會(huì)被使用屑那,就會(huì)產(chǎn)生Heap Leak.
  2. 系統(tǒng)資源泄露(Resource Leak)。主要指程序使用系統(tǒng)分配的資源比如 Bitmap,handle ,SOCKET等沒有使用相應(yīng)的函數(shù)釋放掉艘款,導(dǎo)致系統(tǒng)資源的浪費(fèi)持际,嚴(yán)重可導(dǎo)致系統(tǒng)效能降低,系統(tǒng)運(yùn)行不穩(wěn)定哗咆。
  3. 沒有將基類的析構(gòu)函數(shù)定義為虛函數(shù)蜘欲。當(dāng)基類指針指向子類對(duì)象時(shí),如果基類的析構(gòu)函數(shù)不是virtual晌柬,那么子類的析構(gòu)函數(shù)將不會(huì)被調(diào)用姥份,子類的資源沒有正確是釋放郭脂,因此造成內(nèi)存泄露。

5.new和malloc的區(qū)別

1澈歉、new分配內(nèi)存按照數(shù)據(jù)類型進(jìn)行分配展鸡,malloc分配內(nèi)存按照指定的大小分配;
2埃难、new返回的是指定對(duì)象的指針莹弊,而malloc返回的是void*,因此malloc的返回值一般都需要進(jìn)行類型轉(zhuǎn)化涡尘。
3箱硕、new不僅分配一段內(nèi)存,而且會(huì)調(diào)用構(gòu)造函數(shù)悟衩,malloc不會(huì)剧罩。
4、new分配的內(nèi)存要用delete銷毀座泳,malloc要用free來銷毀惠昔;delete銷毀的時(shí)候會(huì)調(diào)用對(duì)象的析構(gòu)函數(shù),而free則不會(huì)挑势。
5镇防、new是一個(gè)操作符可以重載,malloc是一個(gè)庫函數(shù)潮饱。
6来氧、malloc分配的內(nèi)存不夠的時(shí)候,可以用realloc擴(kuò)容香拉。擴(kuò)容的原理啦扬?new沒用這樣操作。
7凫碌、new如果分配失敗了會(huì)拋出bad_malloc的異常扑毡,而malloc失敗了會(huì)返回NULL。
8盛险、申請(qǐng)數(shù)組時(shí): new[]一次分配所有內(nèi)存瞄摊,多次調(diào)用構(gòu)造函數(shù),搭配使用delete[]苦掘,delete[]多次調(diào)用析構(gòu)函數(shù)换帜,銷毀數(shù)組中的每個(gè)對(duì)象。而malloc則只能sizeof(int) * n鹤啡。

6.共享內(nèi)存相關(guān)api

Linux允許不同進(jìn)程訪問同一個(gè)邏輯內(nèi)存惯驼,提供了一組API,頭文件在sys/shm.h中揉忘。
1)新建共享內(nèi)存shmget

int shmget(key_t key,size_t size,int shmflg);

key:共享內(nèi)存鍵值跳座,可以理解為共享內(nèi)存的唯一性標(biāo)記。

size:共享內(nèi)存大小

shmflag:創(chuàng)建進(jìn)程和其他進(jìn)程的讀寫權(quán)限標(biāo)識(shí)泣矛。

返回值:相應(yīng)的共享內(nèi)存標(biāo)識(shí)符疲眷,失敗返回-1

2)連接共享內(nèi)存到當(dāng)前進(jìn)程的地址空間shmat

void *shmat(int shm_id,const void *shm_addr,int shmflg);

shm_id:共享內(nèi)存標(biāo)識(shí)符

shm_addr:指定共享內(nèi)存連接到當(dāng)前進(jìn)程的地址,通常為0您朽,表示由系統(tǒng)來選擇狂丝。

shmflg:標(biāo)志位

返回值:指向共享內(nèi)存第一個(gè)字節(jié)的指針,失敗返回-1

3)當(dāng)前進(jìn)程分離共享內(nèi)存shmdt

int shmdt(const void *shmaddr);

4)控制共享內(nèi)存shmctl

和信號(hào)量的semctl函數(shù)類似哗总,控制共享內(nèi)存

int shmctl(int shm_id,int command,struct shmid_ds *buf);

shm_id:共享內(nèi)存標(biāo)識(shí)符

command: 有三個(gè)值

IPC_STAT:獲取共享內(nèi)存的狀態(tài)几颜,把共享內(nèi)存的shmid_ds結(jié)構(gòu)復(fù)制到buf中。

IPC_SET:設(shè)置共享內(nèi)存的狀態(tài)讯屈,把buf復(fù)制到共享內(nèi)存的shmid_ds結(jié)構(gòu)蛋哭。

IPC_RMID:刪除共享內(nèi)存

buf:共享內(nèi)存管理結(jié)構(gòu)體。

7.單線程的方式處理高并發(fā)

在單線程模型中涮母,可以采用I/O復(fù)用來提高單線程處理多個(gè)請(qǐng)求的能力谆趾,然后再采用事件驅(qū)動(dòng)模型,基于異步回調(diào)來處理事件來

8.右值引用和左值區(qū)別

右值引用只能用在即將消亡的臨時(shí)對(duì)象上叛本,與返回的左值相比沪蓬,減少了一次構(gòu)造函數(shù)及析構(gòu)函數(shù)調(diào)用,如

int a(){
  return 1;
}
int b=a();
int &&c=a();

b進(jìn)行賦值為左值来候,將a()返回值進(jìn)行拷貝構(gòu)造以后對(duì)a()析構(gòu)跷叉,c則是對(duì)a()的值進(jìn)行引用,保證在C存活時(shí)a()的值也存活营搅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末云挟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子转质,更是在濱河造成了極大的恐慌植锉,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峭拘,死亡現(xiàn)場(chǎng)離奇詭異俊庇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鸡挠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門辉饱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拣展,你說我怎么就攤上這事彭沼。” “怎么了备埃?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵姓惑,是天一觀的道長(zhǎng)褐奴。 經(jīng)常有香客問我,道長(zhǎng)于毙,這世上最難降的妖魔是什么敦冬? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮唯沮,結(jié)果婚禮上脖旱,老公的妹妹穿的比我還像新娘。我一直安慰自己介蛉,他們只是感情好萌庆,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著币旧,像睡著了一般践险。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吹菱,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天捏境,我揣著相機(jī)與錄音,去河邊找鬼毁葱。 笑死垫言,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的倾剿。 我是一名探鬼主播筷频,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼前痘!你這毒婦竟也來了凛捏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤芹缔,失蹤者是張志新(化名)和其女友劉穎坯癣,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體最欠,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡示罗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芝硬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚜点。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拌阴,靈堂內(nèi)的尸體忽然破棺而出绍绘,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布陪拘,位于F島的核電站厂镇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏左刽。R本人自食惡果不足惜捺信,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悠反。 院中可真熱鬧残黑,春花似錦馍佑、人聲如沸斋否。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茵臭。三九已至,卻和暖如春舅世,著一層夾襖步出監(jiān)牢的瞬間旦委,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工雏亚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缨硝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓罢低,卻偏偏與公主長(zhǎng)得像查辩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子网持,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361