C++內(nèi)存管理詳解_第1頁(yè)
C++內(nèi)存管理詳解_第2頁(yè)
C++內(nèi)存管理詳解_第3頁(yè)
C++內(nèi)存管理詳解_第4頁(yè)
C++內(nèi)存管理詳解_第5頁(yè)
已閱讀5頁(yè),還剩21頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C+內(nèi)存管理詳解程序員們經(jīng)常編寫內(nèi)存管理程序,往往提心吊膽。如果不想觸雷,唯一的解決辦法就是發(fā)現(xiàn)所有潛伏的地雷并且排除它們,躲是躲不了的。本文的內(nèi)容比一般教科書的要深入得多,讀者需細(xì)心閱讀,做到真正地通曉內(nèi)存管理。 1、內(nèi)存分配方式內(nèi)存分分配方式式有三種種:(1)從靜靜態(tài)存儲(chǔ)儲(chǔ)區(qū)域分分配。內(nèi)內(nèi)存在程程序編譯譯的時(shí)候候就已經(jīng)經(jīng)分配好好,這塊塊內(nèi)存在在程序的的整個(gè)運(yùn)運(yùn)行期間間都存在在。例如如全局變變量,sstattic變變量。(2)在在棧上創(chuàng)創(chuàng)建。在在執(zhí)行函函數(shù)時(shí),函函數(shù)內(nèi)局局部變量量的存儲(chǔ)儲(chǔ)單元都都可以在在棧上創(chuàng)創(chuàng)建,函函數(shù)執(zhí)行行結(jié)束時(shí)時(shí)這些存存儲(chǔ)單元元自動(dòng)被被釋放。棧棧內(nèi)存分分配運(yùn)算算內(nèi)置于于

2、處理器器的指令令集中,效效率很高高,但是是分配的的內(nèi)存容容量有限限。(3) 從堆上分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc或new申請(qǐng)任意多少的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由我們決定,使用非常靈活,但問題也最多。2、常見的的內(nèi)存錯(cuò)錯(cuò)誤及其其對(duì)策發(fā)發(fā)生內(nèi)存存錯(cuò)誤是是件非常常麻煩的的事情。編編譯器不不能自動(dòng)動(dòng)發(fā)現(xiàn)這這些錯(cuò)誤誤,通常常是在程程序運(yùn)行行時(shí)才能能捕捉到到。而這這些錯(cuò)誤誤大多沒沒有明顯顯的癥狀狀,時(shí)隱隱時(shí)現(xiàn),增增加了改改錯(cuò)的難難度。有有時(shí)用戶戶怒氣沖沖沖地把把你找來來,程序序卻沒有有發(fā)生任任何問題題,你一一走,錯(cuò)錯(cuò)誤又發(fā)發(fā)作了。

3、 常見的內(nèi)存錯(cuò)誤及其對(duì)策如下:* 內(nèi)內(nèi)存分配配未成功功,卻使使用了它它。編程新新手常犯犯這種錯(cuò)錯(cuò)誤,因因?yàn)樗麄儌儧]有意意識(shí)到內(nèi)內(nèi)存分配配會(huì)不成成功。常常用解決決辦法是是,在使使用內(nèi)存存之前檢檢查指針針是否為為NULLL。如如果指針針p是函數(shù)數(shù)的參數(shù)數(shù),那么么在函數(shù)數(shù)的入口口處用aasseert(p!=NULLL)進(jìn)進(jìn)行檢查。如如果是用用malllocc或neww來申請(qǐng)請(qǐng)內(nèi)存,應(yīng)應(yīng)該用iif(pp=NNULLL) 或或if(p!=NULLL)進(jìn)進(jìn)行防錯(cuò)錯(cuò)處理。* 內(nèi)內(nèi)存分配配雖然成成功,但但是尚未未初始化化就引用用它。犯這種種錯(cuò)誤主主要有兩兩個(gè)起因因:一是是沒有初初始化的的觀念;二是誤誤以為內(nèi)內(nèi)

4、存的缺缺省初值值全為零零,導(dǎo)致致引用初初值錯(cuò)誤誤(例如如數(shù)組)。內(nèi)內(nèi)存的缺缺省初值值究竟是是什么并并沒有統(tǒng)統(tǒng)一的標(biāo)標(biāo)準(zhǔn),盡盡管有些些時(shí)候?yàn)闉榱阒?,我我們寧可可信其無無不可信信其有。所所以無論論用何種種方式創(chuàng)創(chuàng)建數(shù)組組,都別別忘了賦賦初值,即即便是賦賦零值也也不可省省略,不不要嫌麻麻煩。* 內(nèi)內(nèi)存分配配成功并并且已經(jīng)經(jīng)初始化化,但操操作越過過了內(nèi)存存的邊界界。例如在在使用數(shù)數(shù)組時(shí)經(jīng)經(jīng)常發(fā)生生下標(biāo)“多1”或者者“少1”的操操作。特特別是在在forr循環(huán)語(yǔ)語(yǔ)句中,循循環(huán)次數(shù)數(shù)很容易易搞錯(cuò),導(dǎo)導(dǎo)致數(shù)組組操作越越界。* 忘忘記了釋釋放內(nèi)存存,造成成內(nèi)存泄泄露。含有這這種錯(cuò)誤誤的函數(shù)數(shù)每被調(diào)調(diào)用一次次就丟

5、失失一塊內(nèi)內(nèi)存。剛剛開始時(shí)時(shí)系統(tǒng)的的內(nèi)存充充足,你你看不到到錯(cuò)誤。終終有一次次程序突突然死掉掉,系統(tǒng)統(tǒng)出現(xiàn)提提示:內(nèi)內(nèi)存耗盡盡。動(dòng)態(tài)內(nèi)內(nèi)存的申申請(qǐng)與釋釋放必須須配對(duì),程程序中mmallloc與與freee的使使用次數(shù)數(shù)一定要要相同,否否則肯定定有錯(cuò)誤誤(neew/ddeleete同同理)。* 釋釋放了內(nèi)內(nèi)存卻繼繼續(xù)使用用它。有有三種情情況:(1)程程序中的的對(duì)象調(diào)調(diào)用關(guān)系系過于復(fù)復(fù)雜,實(shí)實(shí)在難以以搞清楚楚某個(gè)對(duì)對(duì)象究竟竟是否已已經(jīng)釋放放了內(nèi)存存,此時(shí)時(shí)應(yīng)該重重新設(shè)計(jì)計(jì)數(shù)據(jù)結(jié)結(jié)構(gòu),從從根本上上解決對(duì)對(duì)象管理理的混亂亂局面。(2)函函數(shù)的rretuurn語(yǔ)語(yǔ)句寫錯(cuò)錯(cuò)了,注注意不要要返回指指向“棧內(nèi)

6、存存”的“指針”或者“引用”,因?yàn)闉樵搩?nèi)存存在函數(shù)數(shù)體結(jié)束束時(shí)被自自動(dòng)銷毀毀。(3)使使用frree或或delletee釋放了了內(nèi)存后后,沒有有將指針針設(shè)置為為NULLL。導(dǎo)導(dǎo)致產(chǎn)生生“野指針針”?!疽?guī)則則1】用maallooc或neww申請(qǐng)內(nèi)內(nèi)存之后后,應(yīng)該該立即檢檢查指針針值是否否為NUULL。防防止使用用指針值值為NUULL的的內(nèi)存?!疽?guī)則則2】不要要忘記為為數(shù)組和和動(dòng)態(tài)內(nèi)內(nèi)存賦初初值。防防止將未未被初始始化的內(nèi)內(nèi)存作為為右值使使用?!疽?guī)則則3】避免免數(shù)組或或指針的的下標(biāo)越越界,特特別要當(dāng)當(dāng)心發(fā)生生“多1”或者者“少1”操作作。【規(guī)則則4】動(dòng)態(tài)態(tài)內(nèi)存的的申請(qǐng)與與釋放必必須配對(duì)對(duì),防止止內(nèi)

7、存泄泄漏?!疽?guī)則則5】用frree或或delletee釋放了了內(nèi)存之之后,立立即將指指針設(shè)置置為NUULL,防防止產(chǎn)生生“野指針針”。3、指針與與數(shù)組的的對(duì)比C+/C程程序中,指指針和數(shù)數(shù)組在不不少地方方可以相相互替換換著用,讓讓人產(chǎn)生生一種錯(cuò)錯(cuò)覺,以以為兩者者是等價(jià)價(jià)的。數(shù)組要要么在靜靜態(tài)存儲(chǔ)儲(chǔ)區(qū)被創(chuàng)創(chuàng)建(如如全局?jǐn)?shù)數(shù)組),要要么在棧棧上被創(chuàng)創(chuàng)建。數(shù)數(shù)組名對(duì)對(duì)應(yīng)著(而而不是指指向)一一塊內(nèi)存存,其地地址與容容量在生生命期內(nèi)內(nèi)保持不不變,只只有數(shù)組組的內(nèi)容容可以改改變。指針可可以隨時(shí)時(shí)指向任任意類型型的內(nèi)存存塊,它它的特征征是“可變”,所以以我們常常用指針針來操作作動(dòng)態(tài)內(nèi)內(nèi)存。指指針遠(yuǎn)比比數(shù)組

8、靈靈活,但但也更危危險(xiǎn)。下面以以字符串串為例比比較指針針與數(shù)組組的特性性。3.11 修改改內(nèi)容示例33-1中中,字符符數(shù)組aa的容量量是6個(gè)字符符,其內(nèi)內(nèi)容為hhelllo。a的內(nèi)容容可以改改變,如如a00= X。指針針p指向常常量字符符串“worrld”(位于靜態(tài)存儲(chǔ)區(qū),內(nèi)容為world),常量字符串的內(nèi)容是不可以被修改的。從語(yǔ)法上看,編譯器并不覺得語(yǔ)句 p0= X有什么不妥,但是該語(yǔ)句企圖修改常量字符串的內(nèi)容而導(dǎo)致運(yùn)行錯(cuò)誤。char a = “hello”;a0 = X;cout a endl;char *p = “world”; / 注意p指向常量字符串p0 = X; / 編譯器不能發(fā)現(xiàn)

9、該錯(cuò)誤cout p endl;示例3.1 修改數(shù)組和指針的內(nèi)容 3.2 內(nèi)內(nèi)容復(fù)制制與比較較不能對(duì)對(duì)數(shù)組名名進(jìn)行直直接復(fù)制制與比較較。示例例7-33-2中中,若想想把數(shù)組組a的內(nèi)容容復(fù)制給給數(shù)組bb,不能能用語(yǔ)句句 b = aa ,否否則將產(chǎn)產(chǎn)生編譯譯錯(cuò)誤。應(yīng)應(yīng)該用標(biāo)標(biāo)準(zhǔn)庫(kù)函函數(shù)sttrcppy進(jìn)行行復(fù)制。同同理,比比較b和a的內(nèi)容容是否相相同,不不能用iif(bb=aa) 來來判斷,應(yīng)應(yīng)該用標(biāo)標(biāo)準(zhǔn)庫(kù)函函數(shù)sttrcmmp進(jìn)行行比較。語(yǔ)句pp = a 并并不能把把a(bǔ)的內(nèi)容容復(fù)制指指針p,而是是把a(bǔ)的地址址賦給了了p。要想想復(fù)制aa的內(nèi)容容,可以以先用庫(kù)庫(kù)函數(shù)mmallloc為為p申請(qǐng)一一塊容量

10、量為sttrleen(aa)+11個(gè)字符符的內(nèi)存存,再用用strrcpyy進(jìn)行字字符串復(fù)復(fù)制。同同理,語(yǔ)語(yǔ)句iff(p=a) 比較較的不是是內(nèi)容而而是地址址,應(yīng)該該用庫(kù)函函數(shù)sttrcmmp來比比較。/ 數(shù)組組chaar aa = helllo;chhar b110;strrcpyy(b, a); / 不不能用 b = a;if(strrcmpp(b, a) = 0) / 不能能用 iif (b = aa)/ 指針針intt leen = sttrleen(aa);ccharr *pp = (chhar *)mmallloc(sizzeoff(chhar)*(llen+1);sttrcppy(

11、pp,a); / 不不要用 p = a;if(strrcmpp(p, a) = 0) / 不要要用 iif (p = aa)示示例3.2 數(shù)數(shù)組和指指針的內(nèi)內(nèi)容復(fù)制制與比較較 3.3 計(jì)算內(nèi)內(nèi)存容量量用運(yùn)算算符siizeoof可以以計(jì)算出出數(shù)組的的容量(字字節(jié)數(shù))。示例7-3-3(a)中,sizeof(a)的值是12(注意別忘了)。指針p指向a,但是 sizeof(p)的值卻是4。這是因?yàn)閟izeof(p)得到的是一個(gè)指針變量的字節(jié)數(shù),相當(dāng)于sizeof(char*),而不是p所指的內(nèi)存容量。 C+/C語(yǔ)言沒有辦法知道指針?biāo)傅膬?nèi)存容量,除非在申請(qǐng)內(nèi)存時(shí)記住它。 注意當(dāng)數(shù)組作為函數(shù)的參數(shù)進(jìn)行傳

12、遞時(shí),該數(shù)組自動(dòng)退化為同類型的指針。示例7-3-3(b)中,不論數(shù)組a的容量是多少,sizeof(a)始終等于sizeof(char *)。char a = heelloo woorldd;ccharr *pp = a;ccoutt sizzeoff(a) enndl; / 122字節(jié)coout ssizeeof(p) enddl; / 4字節(jié)節(jié)示示例3.3(a) 計(jì)算數(shù)數(shù)組和指指針的內(nèi)內(nèi)存容量量 voidd Fuunc(chaar aa1000)coout ssizeeof(a) enddl; / 4字節(jié)節(jié)而不是是1000字節(jié)示示例3.3(b) 數(shù)組退退化為指指針4、指針參參數(shù)是如如何傳遞遞

13、內(nèi)存的的? 如果函函數(shù)的參參數(shù)是一一個(gè)指針針,不要要指望用用該指針針去申請(qǐng)請(qǐng)動(dòng)態(tài)內(nèi)內(nèi)存。示示例7-4-11中,Teest函函數(shù)的語(yǔ)語(yǔ)句GeetMeemorry(sstr, 2000)并并沒有使使strr獲得期期望的內(nèi)內(nèi)存,sstr依依舊是NNULLL,為什什么?voiid GGetMMemoory(chaar *p, intt nuum)p = (chaar *)maallooc(ssizeeof(chaar) * nnum);voiid TTestt(vooid)chhar *sttr = NUULL;GettMemmoryy(sttr, 1000); / strr 仍然然為 NNULLLs

14、trrcpyy(sttr, heelloo); / 運(yùn)行行錯(cuò)誤示例44.1 試圖用用指針參參數(shù)申請(qǐng)請(qǐng)動(dòng)態(tài)內(nèi)內(nèi)存 毛病出在在函數(shù)GGetMMemoory中中。編譯譯器總是是要為函函數(shù)的每每個(gè)參數(shù)數(shù)制作臨臨時(shí)副本本,指針針參數(shù)pp的副本本是 _p,編編譯器使使 _pp = p。如如果函數(shù)數(shù)體內(nèi)的的程序修修改了_p的內(nèi)內(nèi)容,就就導(dǎo)致參參數(shù)p的內(nèi)容容作相應(yīng)應(yīng)的修改改。這就就是指針針可以用用作輸出出參數(shù)的的原因。在在本例中中,_pp申請(qǐng)了了新的內(nèi)內(nèi)存,只只是把 _p所所指的內(nèi)內(nèi)存地址址改變了了,但是是p絲毫未未變。所所以函數(shù)數(shù)GettMemmoryy并不能能輸出任任何東西西。事實(shí)實(shí)上,每每執(zhí)行一一次Ge

15、etMeemorry就會(huì)會(huì)泄露一一塊內(nèi)存存,因?yàn)闉闆]有用用freee釋放放內(nèi)存。如果非非得要用用指針參參數(shù)去申申請(qǐng)內(nèi)存存,那么么應(yīng)該改改用“指向指指針的指指針”,見示示例4.2。voiid GGetMMemoory22(chhar *pp, iint numm)*pp = (chhar *)mmallloc(sizzeoff(chhar) * numm);voiid TTestt2(vvoidd)chhar *sttr = NUULL;GeetMeemorry2(&sttr, 1000); / 注意參參數(shù)是 &sttr,而而不是sstrstrrcpyy(sttr, heelloo);coout

16、 sstr enddl;freee(sstr);示例44.2用用指向指指針的指指針申請(qǐng)請(qǐng)動(dòng)態(tài)內(nèi)內(nèi)存 由于“指向指指針的指指針”這個(gè)概概念不容容易理解解,我們們可以用用函數(shù)返返回值來來傳遞動(dòng)動(dòng)態(tài)內(nèi)存存。這種種方法更更加簡(jiǎn)單單,見示示例4.3。char *GeetMeemorry3(intt nuum)chhar *p = (chaar *)maallooc(ssizeeof(chaar) * nnum);rretuurn p;voiid TTestt3(vvoidd)chhar *sttr = NUULL;sttr = GeetMeemorry3(1000);strrcpyy(sttr, hee

17、lloo);coout sstr enddl;freee(sstr);示例例4.33 用函函數(shù)返回回值來傳傳遞動(dòng)態(tài)態(tài)內(nèi)存 用函數(shù)返返回值來來傳遞動(dòng)動(dòng)態(tài)內(nèi)存存這種方方法雖然然好用,但但是常常常有人把把retturnn語(yǔ)句用用錯(cuò)了。這這里強(qiáng)調(diào)調(diào)不要用用retturnn語(yǔ)句返返回指向向“棧內(nèi)存存”的指針針,因?yàn)闉樵搩?nèi)存存在函數(shù)數(shù)結(jié)束時(shí)時(shí)自動(dòng)消消亡,見見示例44.4。chaar *GettStrringg(vooid)chhar p = heelloo woorldd;retturnn p; / 編譯器器將提出出警告voiid TTestt4(vvoidd)chhar *sttr = NUULL;st

18、tr = GeetSttrinng(); / sstr 的內(nèi)容容是垃圾圾coout sstr enddl;示例44.4 retturnn語(yǔ)句返返回指向向“棧內(nèi)存存”的指針針 用調(diào)試試器逐步步跟蹤TTestt4,發(fā)發(fā)現(xiàn)執(zhí)行行strr = GettStrringg語(yǔ)句后后strr不再是是NULLL指針針,但是是strr的內(nèi)容容不是“helllo worrld”而是垃垃圾。如如果把示示例4.4改寫寫成示例例4.55,會(huì)怎怎么樣?char *GeetSttrinng2(voiid)chhar *p = helllo worrld;rretuurn p;voiid TTestt5(vvoidd)chha

19、r *sttr = NUULL;strr = GettStrringg2();ccoutt strr enndl;示示例4.5 rretuurn語(yǔ)語(yǔ)句返回回常量字字符串函數(shù)TTestt5運(yùn)行行雖然不不會(huì)出錯(cuò)錯(cuò),但是是函數(shù)GGetSStriing22的設(shè)計(jì)計(jì)概念卻卻是錯(cuò)誤誤的。因因?yàn)镚eetSttrinng2內(nèi)內(nèi)的“helllo worrld”是常量字符串,位于靜態(tài)存儲(chǔ)區(qū),它在程序生命期內(nèi)恒定不變。無論什么時(shí)候調(diào)用GetString2,它返回的始終是同一個(gè)“只讀”的內(nèi)存塊。5、杜絕“野指針”“野指針”不是NULL指針,是指向“垃圾”內(nèi)存的指針。人們一般不會(huì)錯(cuò)用NULL指針,因?yàn)橛胕f語(yǔ)句很容易判

20、斷。但是“野指針”是很危險(xiǎn)的,if語(yǔ)句對(duì)它不起作用。 “野指針”的成因主要有兩種:(1)指指針變量量沒有被被初始化化。任何何指針變變量剛被被創(chuàng)建時(shí)時(shí)不會(huì)自自動(dòng)成為為NULLL指針針,它的的缺省值值是隨機(jī)機(jī)的,它它會(huì)亂指指一氣。所所以,指指針變量量在創(chuàng)建建的同時(shí)時(shí)應(yīng)當(dāng)被被初始化化,要么么將指針針設(shè)置為為NULLL,要要么讓它它指向合合法的內(nèi)內(nèi)存。例例如char *p = NNULLL;chhar *sttr = (ccharr *) maallooc(1100); (2)指指針p被freee或者者delletee之后,沒沒有置為為NULLL,讓讓人誤以以為p是個(gè)合合法的指指針。(3)指指針操作作

21、超越了了變量的的作用范范圍。這這種情況況讓人防防不勝防防,示例例程序如如下:classs Apuubliic:vooid Funnc(vvoidd) couut “FFuncc off cllasss A” Fuunc(); / p是“野指針針”函數(shù)TTestt在執(zhí)行行語(yǔ)句pp-FFuncc()時(shí)時(shí),對(duì)象象a已經(jīng)消消失,而而p是指向向a的,所所以p就成了了“野指針針”。但奇奇怪的是是我運(yùn)行行這個(gè)程程序時(shí)居居然沒有有出錯(cuò),這這可能與與編譯器器有關(guān)。6、有了mmallloc/freee為什什么還要要neww/deelette?malllocc與freee是C+/C語(yǔ)語(yǔ)言的標(biāo)標(biāo)準(zhǔn)庫(kù)函函數(shù),nnew/

22、delletee是C+的運(yùn)算算符。它它們都可可用于申申請(qǐng)動(dòng)態(tài)態(tài)內(nèi)存和和釋放內(nèi)內(nèi)存。對(duì)于非非內(nèi)部數(shù)數(shù)據(jù)類型型的對(duì)象象而言,光光用maalocc/frree無無法滿足足動(dòng)態(tài)對(duì)對(duì)象的要要求。對(duì)對(duì)象在創(chuàng)創(chuàng)建的同同時(shí)要自自動(dòng)執(zhí)行行構(gòu)造函函數(shù),對(duì)對(duì)象在消消亡之前前要自動(dòng)動(dòng)執(zhí)行析析構(gòu)函數(shù)數(shù)。由于于malllocc/frree是是庫(kù)函數(shù)數(shù)而不是是運(yùn)算符符,不在在編譯器器控制權(quán)權(quán)限之內(nèi)內(nèi),不能能夠把執(zhí)執(zhí)行構(gòu)造造函數(shù)和和析構(gòu)函函數(shù)的任任務(wù)強(qiáng)加加于maallooc/ffreee。因此CC+語(yǔ)語(yǔ)言需要要一個(gè)能能完成動(dòng)動(dòng)態(tài)內(nèi)存存分配和和初始化化工作的的運(yùn)算符符neww,以及及一個(gè)能能完成清清理與釋釋放內(nèi)存存工作的的運(yùn)算

23、符符delletee。注意意 neew/ddeleete不不是庫(kù)函函數(shù)。我我們先看看一看mmallloc/freee和neww/deelette如何何實(shí)現(xiàn)對(duì)對(duì)象的動(dòng)動(dòng)態(tài)內(nèi)存存管理,見見示例66。classs Obbjpuubliic :OObj(voiid) coout “Innitiialiizattionn” eendll; Objj(vooid) ccoutt “DDesttroyy” eendll; vvoidd Innitiialiize(voiid) coout “Innitiialiizattionn” eendll; vvoidd Deestrroy(voiid) coout

24、“Deestrroy” Iniitiaalizze(); / 初初始化/a-Desstrooy(); / 清清除工作作freee(aa); / 釋放內(nèi)內(nèi)存voiid UUseNNewDDeleete(voiid)Objj *aa = neww Obbj; / 申請(qǐng)動(dòng)動(dòng)態(tài)內(nèi)存存并且初初始化/deelette aa; / 清清除并且且釋放內(nèi)內(nèi)存示示例6 用malllocc/frree和和neww/deelette如何何實(shí)現(xiàn)對(duì)對(duì)象的動(dòng)動(dòng)態(tài)內(nèi)存存管理類Obbj的函函數(shù)Innitiialiize模模擬了構(gòu)構(gòu)造函數(shù)數(shù)的功能能,函數(shù)數(shù)Desstrooy模擬擬了析構(gòu)構(gòu)函數(shù)的的功能。函函數(shù)UsseMaalloo

25、cFrree中中,由于于 maallooc/ffreee不能執(zhí)執(zhí)行構(gòu)造造函數(shù)與與析構(gòu)函函數(shù),必必須調(diào)用用成員函函數(shù)Innitiialiize和和Desstrooy來完完成初始始化與清清除工作作。函數(shù)數(shù) UsseNeewDeelette則簡(jiǎn)簡(jiǎn)單得多多。所以我我們不要要企圖用用malllocc/frree來來完成動(dòng)動(dòng)態(tài)對(duì)象象的內(nèi)存存管理,應(yīng)應(yīng)該用nnew/delletee。由于于內(nèi)部數(shù)數(shù)據(jù)類型型的“對(duì)象”沒有構(gòu)構(gòu)造與析析構(gòu)的過過程,對(duì)對(duì)它們而而言maallooc/ffreee和neww/deelette是等等價(jià)的。既然nnew/delletee的功能能完全覆覆蓋了mmallloc/freee,為為

26、什么CC+不不把maallooc/ffreee淘汰出出局呢?這是因因?yàn)镃+程序序經(jīng)常要要調(diào)用CC函數(shù),而而C程序只只能用mmallloc/freee管理理動(dòng)態(tài)內(nèi)內(nèi)存。如如果用ffreee釋放“neww創(chuàng)建的的動(dòng)態(tài)對(duì)對(duì)象”,那么么該對(duì)象象因無法法執(zhí)行析析構(gòu)函數(shù)數(shù)而可能能導(dǎo)致程程序出錯(cuò)錯(cuò)。如果果用deelette釋放放“malllocc申請(qǐng)的的動(dòng)態(tài)內(nèi)內(nèi)存”,理論論上講程程序不會(huì)會(huì)出錯(cuò),但但是該程程序的可可讀性很很差。所所以neew/ddeleete必必須配對(duì)對(duì)使用,malloc/free也一樣。 7、內(nèi)存耗耗盡怎么么辦?如如果在申申請(qǐng)動(dòng)態(tài)態(tài)內(nèi)存時(shí)時(shí)找不到到足夠大大的內(nèi)存存塊,mmallloc和和n

27、eww將返回回NULLL指針針,宣告告內(nèi)存申申請(qǐng)失敗敗。通常常有三種種方式處處理“內(nèi)存耗耗盡”問題。 (1)判斷斷指針是是否為NNULLL,如果果是則馬馬上用rretuurn語(yǔ)語(yǔ)句終止止本函數(shù)數(shù)。例如如:vooid Funnc(vvoidd)A *a = neew AA;iif(aa = NUULL)retturnn;(2)判斷斷指針是是否為NNULLL,如果果是則馬馬上用eexitt(1)終止整整個(gè)程序序的運(yùn)行行。例如如:vooid Funnc(vvoidd)A *a = nnew A;if(a = NNULLL)ccoutt “MMemoory Exhhausstedd” eendll;e

28、xiit(11); (3)為為neww和malllocc設(shè)置異異常處理理函數(shù)。例例如Viisuaal CC+可可以用_sett_neew_hhandder函函數(shù)為nnew設(shè)設(shè)置用戶戶自己定定義的異異常處理理函數(shù),也也可以讓讓malllocc享用與與neww相同的的異常處處理函數(shù)數(shù)。詳細(xì)細(xì)內(nèi)容請(qǐng)請(qǐng)參考CC+使使用手冊(cè)冊(cè)。上述(1)(2)方式使用最普遍。如果一個(gè)函數(shù)內(nèi)有多處需要申請(qǐng)動(dòng)態(tài)內(nèi)存,那么方式(1)就顯得力不從心(釋放內(nèi)存很麻煩),應(yīng)該用方式(2)來處理。很多人人不忍心心用exxit(1),問問:“不編寫寫出錯(cuò)處處理程序序,讓操操作系統(tǒng)統(tǒng)自己解解決行不不行?”不行。如如果發(fā)生生“內(nèi)存耗耗盡”

29、這樣的的事情,一一般說來來應(yīng)用程程序已經(jīng)經(jīng)無藥可可救。如如果不用用exiit(11) 把把壞程序序殺死,它它可能會(huì)會(huì)害死操操作系統(tǒng)統(tǒng)。道理理如同:如果不不把歹徒徒擊斃,歹歹徒在老老死之前前會(huì)犯下下更多的的罪。有一個(gè)個(gè)很重要要的現(xiàn)象象要告訴訴大家。對(duì)對(duì)于322位以上上的應(yīng)用用程序而而言,無無論怎樣樣使用mmallloc與與neww,幾乎乎不可能能導(dǎo)致“內(nèi)存耗耗盡”。我在在Winndowws 998下用用Vissuall C+編寫寫了測(cè)試試程序,見見示例77。這個(gè)個(gè)程序會(huì)會(huì)無休止止地運(yùn)行行下去,根根本不會(huì)會(huì)終止。因因?yàn)?22位操作作系統(tǒng)支支持“虛存”,內(nèi)存存用完了了,自動(dòng)動(dòng)用硬盤盤空間頂頂替。我我

30、只聽到到硬盤嘎嘎吱嘎吱吱地響,Window 98已經(jīng)累得對(duì)鍵盤、鼠標(biāo)毫無反應(yīng)。我可以以得出這這么一個(gè)個(gè)結(jié)論:對(duì)于332位以以上的應(yīng)應(yīng)用程序序,“內(nèi)存耗耗盡”錯(cuò)誤處處理程序序毫無用用處。這這下可把把Uniix和Winndowws程序序員們樂樂壞了:反正錯(cuò)錯(cuò)誤處理理程序不不起作用用,我就就不寫了了,省了了很多麻麻煩。我不想想誤導(dǎo)讀讀者,必必須強(qiáng)調(diào)調(diào):不加加錯(cuò)誤處處理將導(dǎo)導(dǎo)致程序序的質(zhì)量量很差,千千萬不可可因小失失大。vvoidd maain(voiid)flloatt *pp = NULLL;whiile(TRUUE)p = neew ffloaat1100000000;coout “eaat m

31、memoory” enddl;iff(p=NUULL)exiit(11);示例77試圖耗耗盡操作作系統(tǒng)的的內(nèi)存 8、maallooc/ffreee 的使使用要點(diǎn)點(diǎn)函數(shù)mmallloc的的原型如如下:void * mmallloc(sizze_tt siize); 用maallooc申請(qǐng)請(qǐng)一塊長(zhǎng)長(zhǎng)度為llenggth的的整數(shù)類類型的內(nèi)內(nèi)存,程程序如下下:int *p = (iint *) malllocc(siizeoof(iint) * lenngthh); 我們應(yīng)應(yīng)當(dāng)把注注意力集集中在兩兩個(gè)要素素上:“類型轉(zhuǎn)轉(zhuǎn)換”和“sizzeoff”。* mmallloc返回值值的類型型是vooid *,

32、所所以在調(diào)調(diào)用maallooc時(shí)要要顯式地地進(jìn)行類類型轉(zhuǎn)換換,將vvoidd * 轉(zhuǎn)換成成所需要要的指針針類型。* mmallloc函函數(shù)本身身并不識(shí)識(shí)別要申申請(qǐng)的內(nèi)內(nèi)存是什什么類型型,它只只關(guān)心內(nèi)內(nèi)存的總總字節(jié)數(shù)數(shù)。我們們通常記記不住iint, flloatt等數(shù)據(jù)據(jù)類型的的變量的的確切字字節(jié)數(shù)。例例如innt變量量在166位系統(tǒng)統(tǒng)下是22個(gè)字節(jié)節(jié),在332位下下是4個(gè)字節(jié)節(jié);而ffloaat變量量在166位系統(tǒng)統(tǒng)下是44個(gè)字節(jié)節(jié),在332位下下也是44個(gè)字節(jié)節(jié)。最好好用以下下程序作作一次測(cè)測(cè)試:cout sizzeoff(chhar) enndl;couut ssizeeof(intt)

33、eendll;coout sizzeoff(unnsiggnedd innt) enddl;ccoutt siizeoof(llongg) eendll;coout sizzeoff(unnsiggnedd loong) enndl;couut ssizeeof(flooat) enndl;couut ssizeeof(douublee) eendll;coout sizzeoff(vooid *) enddl; 在maallooc的“()”中中使用ssizeeof運(yùn)運(yùn)算符是是良好的的風(fēng)格,但但要當(dāng)心心有時(shí)我我們會(huì)昏昏了頭,寫寫出 pp = malllocc(siizeoof(pp)這這樣的程程序來。* 函函數(shù)frree的的原型如如下:void freee( voiid * meembllockk ); 為什么么freee 函函數(shù)不象象malllocc函數(shù)那那樣復(fù)雜雜呢?這這是因?yàn)闉橹羔榩p的類型型以及它它所指的的內(nèi)存的的容量事事先都是是知道的的,語(yǔ)句句freee(pp)能正正確地釋釋放內(nèi)存存。如果果p是

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論