国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

C++語言內(nèi)存分配研究

2014-04-29 04:03:01張會
計算機時代 2014年5期
關(guān)鍵詞:編譯器鏈表指針

張會

摘 要: 詳細闡述了C++編譯器的內(nèi)存分配形式,給出了堆、棧、文字常量區(qū)、寄存器區(qū)、靜態(tài)區(qū)、程序代碼區(qū)的分配策略,分析了內(nèi)存分配中易產(chǎn)生的問題及導(dǎo)致程序運行出錯的原因和解決辦法,從而避免程序異常和內(nèi)存錯誤,保證程序的健壯性和正確性。

關(guān)鍵詞: 內(nèi)存; 堆; 棧; C++語言

中圖分類號:TP312 文獻標志碼:A 文章編號:1006-8228(2014)05-44-03

Abstract: The memory allocation strategy C++ compiler is described in detail in this paper. The distribution strategy of heap, stack, literals memory, register memory in C++ language is given. The causes and the solution of memory allocation problems and program running error are analyzed to avoid exception and memory errors, and guarantee the correctness and robustness of program.

Key words: memory; heap; stack; C++ language

0 引言

C++編譯器根據(jù)數(shù)據(jù)在內(nèi)存中的生存期不同,將用戶使用的內(nèi)存分為程序區(qū)、靜態(tài)存儲區(qū)和動態(tài)存儲區(qū)三個區(qū)域,其中動態(tài)存儲區(qū)又分為堆區(qū)、棧區(qū)和寄存器區(qū)。

1 內(nèi)存分配形式

C++中內(nèi)存分配形式有以下六種。

1.1 棧區(qū)(stack)

棧由編譯器自動分配及釋放,用于存放函數(shù)參數(shù)值,局部變量值等。棧是一塊連續(xù)的內(nèi)存區(qū)域,它的大小為2M固定常數(shù),因此程序中的變量能從棧中獲取空間較少。若棧的剩余空間大于所申請空間,編譯器將為程序提供??臻g,且按照向低地址生長方向分配連續(xù)的內(nèi)存空間;若申請的空間超過棧的剩余空間,將報異常,提示棧溢出(overflow)[1]。

在調(diào)用函數(shù)時,第一個進棧的是被調(diào)用函數(shù)下一行的內(nèi)存地址,再是函數(shù)參數(shù),參數(shù)入棧的順序自右向左,再是函數(shù)的局部變量。函數(shù)調(diào)用結(jié)束后,首先出棧的是被調(diào)函數(shù)中的局部變量,再是參數(shù),次序是自左向右,所有變量和參數(shù)都出棧后,棧頂指針指到調(diào)用函數(shù)的下一行內(nèi)存地址,程序根據(jù)該地址跳轉(zhuǎn)到函數(shù)調(diào)用處的下一行自動執(zhí)行。入棧數(shù)據(jù)的內(nèi)存地址隨著入棧順序的先后向著內(nèi)存地址減小的方向增長,隨著數(shù)據(jù)不斷入棧,內(nèi)存地址不斷變小。由于棧的先進后出原則,棧不會產(chǎn)生內(nèi)存碎片。雖然棧內(nèi)存小,但效率高,棧中存儲的數(shù)據(jù)只在函數(shù)內(nèi)有效,函數(shù)調(diào)用結(jié)束會因為數(shù)據(jù)出棧而被釋放。

1.2 堆區(qū)(heap)

堆內(nèi)存由程序員分配及釋放,若程序員在程序中未釋放,則在程序運行結(jié)束后,由操作系統(tǒng)回收。堆是不連續(xù)的空閑內(nèi)存區(qū)域,各塊區(qū)域由鏈表連接起來,其內(nèi)存大小由系統(tǒng)中虛擬內(nèi)存來確定,因此其空間較大,可以存放大量數(shù)據(jù)。

堆區(qū)分配內(nèi)存空間時,系統(tǒng)會遍歷用于記錄內(nèi)存空閑塊的鏈表,首次找到一個空間大于所申請空間的堆結(jié)點時,將該結(jié)點從鏈表中刪除。并將該結(jié)點的內(nèi)存分配給程序,同時在這塊內(nèi)存區(qū)域首地址處記錄本次內(nèi)存分配大小,程序員在用delete或free釋放內(nèi)存時,以此識別要刪除內(nèi)存大小并正確刪除該段內(nèi)存。若申請的內(nèi)存空間與堆結(jié)點上的內(nèi)存空間不相等,則系統(tǒng)會自動將堆結(jié)點上多余內(nèi)存空間回收到空閑鏈表中。堆區(qū)在分配內(nèi)存時,鏈表中地址遍歷方向是由低向高,因此堆區(qū)分配內(nèi)存時是按照向高地址生長的方向分配不連續(xù)內(nèi)存空間[1]。堆內(nèi)存分配是由程序員進行分配及釋放,速度較慢,易產(chǎn)生內(nèi)存碎片。

堆是不連續(xù)的內(nèi)存區(qū)域,由鏈表將其串接起來的空閑塊,其不能像棧一樣可以為其中的某個存儲單元命名,堆中的每個內(nèi)存單元都是匿名的,對堆的訪問只能先在堆中申請內(nèi)存,再把申請內(nèi)存的首地址保存在一個指針中,再通過指針來訪問內(nèi)存。在C++中用malloc()和new關(guān)鍵字申請堆內(nèi)存。寄存器區(qū)一般用于保存棧頂指針和指令指針。

1.4 靜態(tài)區(qū)(static)

全局變量和靜態(tài)變量的存儲是放在一塊的,已初始化的全局變量和靜態(tài)變量放在一塊區(qū)域,未初始化的全局變量和靜態(tài)變量存放于相鄰的另一塊區(qū)域,內(nèi)存在程序結(jié)束后由系統(tǒng)釋放。靜態(tài)變量的空間在程序編譯階段進行分配,所分配內(nèi)存在程序整個運行期間都存在[2]。

1.6 程序代碼區(qū)

存放函數(shù)體的二進制代碼。

2 內(nèi)存分配中若干問題的分析

如果對內(nèi)存分配策略理解不清楚,且程序設(shè)計不當,就極易引起對運行結(jié)果異常,且難以捕獲由內(nèi)存分配所引起的錯誤。

本程序的輸出結(jié)果既不是隨機值,也不是3而是4,是由棧空間的連續(xù)分配所引起。在main()函數(shù)中,首先調(diào)用fun()函數(shù),此時fun1()代碼行地址入棧,接著fun()中的局部變量x入棧,fun()調(diào)用結(jié)束后把x的內(nèi)存地址值返回給main()函數(shù)中的p指針,此時棧中的x已經(jīng)出棧。接著在main()中調(diào)用fun1()函數(shù),此時對fun1()中的a進行棧內(nèi)存的分配,其分配的棧空間正好是fun()函數(shù)中x變量所釋放的內(nèi)存,對該內(nèi)存賦值4后,回到主函數(shù),此時??臻g的a變量內(nèi)存被釋放,而此時p指針從未改變,與此同時,程序沒有其他語句代碼或變量需要分配??臻g,因此p指針所指的??臻g的值未被覆蓋,保留最后一次所賦值4,故程序最后輸出的值是4。因此掌握了內(nèi)存中存儲空間的分配情況及原理,不難分析其異常的運行結(jié)果。

為防止讓指向常量的指針對所指常量進行值的改變,解決的辦法是把p聲明成常量指針,如:const char *p;以保證不能改變所指常量的值,若試圖通過指針改變常量的值,在編譯檢查時將報錯,不致于如上述程序段發(fā)生運行時錯誤。

2.3 堆區(qū)內(nèi)存分配

堆中的內(nèi)存是匿名的,對堆內(nèi)存進行訪問只能通過指針進行訪問。通過指針訪問堆內(nèi)存時,一定要注意防止內(nèi)存泄露。內(nèi)存泄露是指程序從堆中分配的內(nèi)存塊該內(nèi)存釋放后即存放了其他數(shù)據(jù),但p中的地址值仍然是所釋放那段內(nèi)存的地址值,因此第5行輸出*p的值是所釋放那段內(nèi)存中已存放的隨機值。第6行p1指向新申請的一段內(nèi)存,由于編譯器會默認將釋放掉的內(nèi)存空間回收然后分配給新開辟的空間,因此第6行p1其實指向的是剛通p所釋放掉的空間3 內(nèi)存分配中存在的其他情況

內(nèi)存分配發(fā)生的異常,編譯器不能通過語法檢查發(fā)現(xiàn),通常會發(fā)生程序運行結(jié)果異常,該類錯誤不易被捕捉,從而給程序員檢查程序錯誤帶來不便,因此在寫程序時盡量避免內(nèi)存分配錯誤。常見的內(nèi)存操作異常如下。

⑴ 內(nèi)存分配失敗卻直接使用,如返回一個NULL指針。

⑵ 訪問內(nèi)存時超出了內(nèi)存分配的邊界。越界的內(nèi)存可能保存其他變量的值,訪問該內(nèi)存變量的值,可能產(chǎn)生異常,導(dǎo)致程序的終止甚至崩潰[4]。

⑶ 動態(tài)申請了內(nèi)存空間如鏈表,而未動態(tài)釋放內(nèi)存空間,或未完全釋放,只釋放了鏈表中的表頭指針所指向結(jié)點,而未釋放鏈表中的各個結(jié)點的內(nèi)存空間,從而造成內(nèi)存泄露。

(4)訪問已經(jīng)釋放的內(nèi)存,釋放已經(jīng)釋放的內(nèi)存。從而導(dǎo)致程序無法正確運行,得到無效值。

4 結(jié)束語

本文闡述了C++編譯器的內(nèi)存分配形式,提出了堆、棧、文字常量區(qū),寄存器區(qū)的分配策略,分析了內(nèi)存分配中易產(chǎn)生的問題和原因,同時給出了因內(nèi)存分配而導(dǎo)致程序錯誤的解決辦法,總之要解決程序中因內(nèi)存分配所產(chǎn)生的問題,其前提是必須要清楚內(nèi)存分配策略。通過本文對C++中內(nèi)存分配策略的研究,可以使讀者在以后的程序編寫中有效的避免內(nèi)存分配錯誤,從而保證程序的健壯性和正確性。

參考文獻:

[1] 王文龍.C/C++數(shù)據(jù)內(nèi)存分配和指針使用中若干問題的分析[J].喀什

師范學院學報,2013.34(6):36-37

[2] 韓雨澇.C語言動態(tài)內(nèi)存分配研究及應(yīng)用[J].計算機時代,2009.5:

33-34

[3] 王金玲,柴萬東.C++動態(tài)內(nèi)存分配研究[J].赤峰學院學報,2009.25

(4):19-20

[4] Eri R.Hanly.C語言詳解[M].人民郵電出版社,2007.

猜你喜歡
編譯器鏈表指針
基于相異編譯器的安全計算機平臺交叉編譯環(huán)境設(shè)計
基于二進制鏈表的粗糙集屬性約簡
偷指針的人
娃娃畫報(2019年5期)2019-06-17 16:58:10
跟麥咭學編程
基于鏈表多分支路徑樹的云存儲數(shù)據(jù)完整性驗證機制
為什么表的指針都按照順時針方向轉(zhuǎn)動
基于改進Hough變換和BP網(wǎng)絡(luò)的指針儀表識別
電測與儀表(2015年5期)2015-04-09 11:30:42
鏈表方式集中器抄表的設(shè)計
電測與儀表(2014年1期)2014-04-04 12:00:22
ARM Cortex—MO/MO+單片機的指針變量替換方法
通用NC代碼編譯器的設(shè)計與實現(xiàn)
交城县| 盐山县| 航空| 五寨县| 德昌县| 灌阳县| 清水河县| 威宁| 瑞丽市| 扶沟县| 昂仁县| 乌兰浩特市| 绥化市| 邻水| 班戈县| 侯马市| 岳西县| 天门市| 隆安县| 九龙县| 成都市| 巫山县| 眉山市| 嘉兴市| 河曲县| 蒙自县| 通山县| 沛县| 崇礼县| 永德县| 赤城县| 兰考县| 大荔县| 五台县| 定南县| 花莲市| 泌阳县| 临沧市| 沙坪坝区| 青龙| 隆林|