關(guān)青苗 蔣爭明
Abstract: Memory management in C++ is a big issue for the users who rely on those languages in their project. And memory management two aspects in its domain, first, make it work right; second, make it fast. Every programmer knows it must be listed like this, because code run dizzily fast, but dont work under control, is no use at all. If memory allocated but not released correctly, then memory leak generate. So the defensive programming is a effective method to avoid the error.
Key word:Memory manage, memory leak, defensive programming
一、引言
內(nèi)存管理的主要內(nèi)容有兩點(diǎn):1,將內(nèi)存正確的分配和釋放; 2,讓計(jì)算機(jī)能快速的執(zhí)行內(nèi)存的分配和釋放。我們都知道這個(gè)順序不能顛倒,因?yàn)榧词钩绦蜻\(yùn)行的很快,但是沒有正確的分配和釋放內(nèi)存,這個(gè)程序?qū)ξ覀円矝]有多少用處。
二、內(nèi)存的分配
C++分配內(nèi)存按分配類型分為三種。
1、全局靜態(tài)量,在文件的全局變量區(qū)定義一整型變量,諸如static int num = 0定義的變量,這種變量在程序的開始運(yùn)行到結(jié)束運(yùn)行的全部生命周期都存在,而且此變量名在后面程序內(nèi)不可以重復(fù)定義,如果重復(fù)定義,編譯器會(huì)提示錯(cuò)誤,將無法通過編譯而生成可運(yùn)行文件。此種分配類型分配給變量的內(nèi)存位置是全局區(qū)。程序的開始運(yùn)行時(shí),由編譯器分配到內(nèi)存的全局變量區(qū),直到程序結(jié)束,變量所使用的內(nèi)存被編譯器釋放。
2、局部變量,典型的是在函數(shù)或者語句內(nèi)部定義的變量,比如for(int i=0; i 3、使用運(yùn)算符new分配的變量,比如:new int[10], 或者malloc (10*sizeof(int)),此種方式分配的內(nèi)存位置存在一個(gè)稱為堆區(qū)的內(nèi)存上,注意它和數(shù)據(jù)結(jié)構(gòu)的堆是不同的,實(shí)現(xiàn)方式類似于鏈表。一般來說,此種分配方式是在要分配的內(nèi)存無法預(yù)知的情況下,它由程序員手動(dòng)分配,手動(dòng)釋放。如果程序員在使用此類型變量不正確,將導(dǎo)致各種問題的產(chǎn)生。 三、常見錯(cuò)誤及對(duì)策 1、對(duì)上面提到的全局靜態(tài)變量num,在程序的使用過程中,就是要注意你的每次改變,都是全局性的,所以盡量不要輕易改變它除非你想這么做。如果為了防止程序的其他用戶改變你不希望改變的全局變量,你可以在它前面加上const來限定。比如:const int num = 0;這樣別的用戶在試圖改變之,編譯器就會(huì)給出警告。 2、而使用局部變量的時(shí)候,容易出現(xiàn)的錯(cuò)誤就是對(duì)變量的生存周期不了解產(chǎn)生的錯(cuò)誤,在變量的生存期內(nèi)重復(fù)定義了變量。我們可以使用長命名法來命名變量,這樣變量重復(fù)定義的機(jī)會(huì)就大大降低,而且變量名在使用過程中,其意義也更加明顯。 3、而使用new分配的變量內(nèi)存,最容易出現(xiàn)的錯(cuò)誤是,沒有正確的釋放。常見的錯(cuò)誤比如,使用int *p = new int來分配一組整形的數(shù)組;或者使用delete p來釋放int *p = new int[10]分配的數(shù)組;或者使用delete運(yùn)算符再次釋放已經(jīng)釋放過的內(nèi)存塊,這樣會(huì)產(chǎn)生無法預(yù)料的后果。這樣產(chǎn)生的錯(cuò)誤,編譯器無法幫組我們識(shí)別,所以這種錯(cuò)誤更加隱蔽,而且在調(diào)試的時(shí)候更難發(fā)現(xiàn)。我們的對(duì)策就是可以使用一個(gè)對(duì)象的計(jì)數(shù)器,來監(jiān)視對(duì)象的創(chuàng)建和釋放,采取一些斷言,比如assert函數(shù),來以防止我們錯(cuò)誤的調(diào)用delete運(yùn)算符。 四、應(yīng)用實(shí)例 下面我們使用一段代碼來說明我們的3.3中的方法,采用的IDE是vs2010,平臺(tái)是win7 64位Intel機(jī)器。 #include "stdio.h" static int counter_for_object = 0; #define NULL 0 class monster { private: int hp; int mp; public: monster():hp(0),mp(0){ counter_for_object ++;} ~monster(){counter_for_object--; } }; int _tmain(int argc, _TCHAR* argv[]) { monster *groupOfMonsters = new monster[10]; delete [] groupOfMonsters; groupOfMonsters = NULL; printf("end of code\n"); return 0; } 如果在打印界面的end of code之前出現(xiàn)的counter_for_object最后不為0,則可判定出內(nèi)存泄露. 五、結(jié)束語 合理的分配內(nèi)存和釋放內(nèi)存,是程序員的在編寫合理的代碼時(shí)最重要的任務(wù),而采用合理的策略和良好的代碼習(xí)慣,是我們能保證代碼質(zhì)量的工具。 參考文獻(xiàn) [1] Scott Meyers, Effective C++[M], Addison-Wesley, 1992. [2] 沈被娜,劉祖照. 計(jì)算機(jī)軟件基礎(chǔ)(第三版)[M]. 清華大學(xué)出版社.2000. (作者單位:廣東科技學(xué)院)