• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            單鏈DNA

            換了個(gè)地址:http://www.cnblogs.com/vizhen/

             

            淺析C++中內(nèi)存分配方式

              在C++中,內(nèi)存分為5大存儲(chǔ)區(qū)堆區(qū)、棧區(qū)、全局區(qū)、文字常量區(qū)、程序代碼區(qū)

             

            內(nèi)存區(qū)域 說明
            棧區(qū)(stack)    由編譯器自動(dòng)分配釋放,存放為運(yùn)行函數(shù)而分配的局部變量、函數(shù)參數(shù)、返回?cái)?shù)據(jù)、返回地址等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
            堆區(qū)(heap)   一般有程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能有系統(tǒng)回收。分配方式類似于鏈表。
            全局區(qū)(static) 存放全局變量、靜態(tài)數(shù)據(jù)、常量。程序結(jié)束后有系統(tǒng)釋放。
            文字常量區(qū)   常量字符串就是放在這里;程序結(jié)束后有系統(tǒng)釋放。
            程序代碼區(qū)   存放函數(shù)體(類成員函數(shù)和全局函數(shù))的二進(jìn)制代碼。

            實(shí)例分析:

            int a=0; //全局區(qū)初始化區(qū) char *p1;    //全局區(qū)未初始化區(qū) static char b;      //全局區(qū)未初始化靜態(tài)變量 int main() { int c; //棧區(qū)臨時(shí)變量 char s[]="abc"; //棧區(qū)臨時(shí)數(shù)組變量 char *p2; //棧區(qū)臨時(shí)指針變量 char *p3="123";    //常量區(qū)常量,棧區(qū)指針變量 static int d=0; //全局初始化區(qū)靜態(tài)變量 p1=new char[10]; //堆區(qū)分配10個(gè)字符空間 p2=new char[20]; //堆區(qū)分配20個(gè)字符空間 strcpy(p1,"123"); //"123"放在常量區(qū),編譯器有可能將它與p3所指向的區(qū)域相同

            }

            內(nèi)存分配方式

          1. 從靜態(tài)存儲(chǔ)區(qū)分配

            內(nèi)存在程序編譯時(shí)就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。速度快、不容易出錯(cuò),因?yàn)橄到y(tǒng)會(huì)善后。例如全局變量,static常量。
          2. 從棧上分配

            在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)部局部變量的存儲(chǔ)單元都在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器指令集中,效率很高,但分配的內(nèi)存容量有限。
          3. 從堆上分配

            也叫動(dòng)態(tài)分配。程序在運(yùn)行時(shí)用malloc或new申請任意大小的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期有程序員決定,使用靈活。如果在堆上分配了空間,就有責(zé)任回收它,否則運(yùn)行的程序會(huì)出現(xiàn)內(nèi)存泄露,另外頻繁的分配和釋放不同大小的堆空間將會(huì)產(chǎn)生對內(nèi)碎塊。

             

            堆和棧究區(qū)別

            主要的區(qū)別由以下幾點(diǎn):
               1.管理方式:對于棧來講,是由編譯器自動(dòng)管理,無需我們手工控制;對于堆來說,釋放工作由程序員控制,容易產(chǎn)生memory leak。

               2.空間大小:一般來講在32位系統(tǒng)下,堆內(nèi)存可以達(dá)到4G的空間,從這個(gè)角度來看堆內(nèi)存幾乎是沒有什么限制的。但是對于棧來講,一般都是有一定的空間大小 的,例如,在VC6下面,默認(rèn)的棧空間大小是1M(好像是,記不清楚了)。當(dāng)然,我們可以修改:
            打開工程,依次操作菜單如下:Project->Setting->Link,在Category 中選中Output,然后在Reserve中設(shè)定堆棧的最大值和commit。
                注意:reserve最小值為4Byte;commit是保留在虛擬內(nèi)存的頁文件里面,它設(shè)置的較大會(huì)使棧開辟較大的值,可能增加內(nèi)存的開銷和啟動(dòng)時(shí)間。
              

               3.碎片問題:對于堆來講,頻繁的new/delete勢必會(huì)造成內(nèi)存空間的不連續(xù),從而造成大量的碎片,使程序效率降低。對于棧來講,則不會(huì)存在這個(gè)問題, 因?yàn)闂J窍冗M(jìn)后出的隊(duì)列,他們是如此的一一對應(yīng),以至于永遠(yuǎn)都不可能有一個(gè)內(nèi)存塊從棧中間彈出,在他彈出之前,在他上面的后進(jìn)的棧內(nèi)容已經(jīng)被彈出,詳細(xì)的 可以參考數(shù)據(jù)結(jié)構(gòu),這里我們就不再一一討論了。
             

               4.生長方向:對于堆來講,生長方向是向上的,也就是向著內(nèi)存地址增加的方向;對于棧來講,它的生長方向是向下的,是向著內(nèi)存地址減小的方向增長。
            分配方式:堆都是動(dòng)態(tài)分配的,沒有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動(dòng)態(tài)分配。靜態(tài)分配是編譯器完成的,比如局部變量的分配。動(dòng)態(tài)分配由 alloca函數(shù)進(jìn)行分配,但是棧的動(dòng)態(tài)分配和堆是不同的,他的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放,無需我們手工實(shí)現(xiàn)。

                5.分配效率:棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計(jì)算機(jī)會(huì)在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率比 較高。堆則是C/C++函數(shù)庫提供的,它的機(jī)制是很復(fù)雜的,例如為了分配一塊內(nèi)存,庫函數(shù)會(huì)按照一定的算法(具體的算法可以參考數(shù)據(jù)結(jié)構(gòu)/操作系統(tǒng))在堆內(nèi)存中搜索可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由于內(nèi)存碎片太多),就有可能調(diào)用系統(tǒng)功能去增加程序數(shù)據(jù)段的內(nèi)存空間,這樣就有機(jī)會(huì)分 到足夠大小的內(nèi)存,然后進(jìn)行返回。顯然,堆的效率比棧要低得多。

            常見的內(nèi)存錯(cuò)誤及其對策:

            發(fā)生內(nèi)存錯(cuò)誤是件非常麻煩的事情。編譯器不能自動(dòng)發(fā)現(xiàn)這些錯(cuò)誤,通常是在程序運(yùn)行時(shí)才能捕捉到。而這些錯(cuò)誤大多沒有明顯的癥狀,時(shí)隱時(shí)現(xiàn),增加了改錯(cuò)的難度。常見的內(nèi)存錯(cuò)誤及其對策如下:

              * 內(nèi)存分配未成功,卻使用了它。

              編程新手常犯這種錯(cuò)誤,因?yàn)樗麄儧]有意識到內(nèi)存分配會(huì)不成功。常用解決辦法是,在使用內(nèi)存之前檢查指針是否為NULL。如果指針p是函數(shù)的參數(shù),那么在函數(shù)的入口處用assert(p!=NULL)進(jìn)行檢查。如果是用malloc或new來申請內(nèi)存,應(yīng)該用if(p==NULL) 或if(p!=NULL)進(jìn)行防錯(cuò)處理。

                 * 內(nèi)存分配雖然成功,但是尚未初始化就引用它。

              犯這種錯(cuò)誤主要有兩個(gè)起因:一是沒有初始化的觀念;二是誤以為內(nèi)存的缺省初值全為零,導(dǎo)致引用初值錯(cuò)誤(例如數(shù)組)。 內(nèi)存的缺省初值究竟是什么并沒有統(tǒng)一的標(biāo)準(zhǔn),盡管有些時(shí)候?yàn)榱阒担覀儗幙尚牌錈o不可信其有。所以無論用何種方式創(chuàng)建數(shù)組,都別忘了賦初值,即便是賦零值也不可省略,不要嫌麻煩。

              * 內(nèi)存分配成功并且已經(jīng)初始化,但操作越過了內(nèi)存的邊界。

              例如在使用數(shù)組時(shí)經(jīng)常發(fā)生下標(biāo)“多1”或者“少1”的操作。特別是在for循環(huán)語句中,循環(huán)次數(shù)很容易搞錯(cuò),導(dǎo)致數(shù)組操作越界。

              * 忘記了釋放內(nèi)存,造成內(nèi)存泄露。

              含有這種錯(cuò)誤的函數(shù)每被調(diào)用一次就丟失一塊內(nèi)存。剛開始時(shí)系統(tǒng)的內(nèi)存充足,你看不到錯(cuò)誤。終有一次程序突然死掉,系統(tǒng)出現(xiàn)提示:內(nèi)存耗盡。

              動(dòng)態(tài)內(nèi)存的申請與釋放必須配對,程序中malloc與free的使用次數(shù)一定要相同,否則肯定有錯(cuò)誤(new/delete同理)。

              * 釋放了內(nèi)存卻繼續(xù)使用它。

              有三種情況:

              (1)程序中的對象調(diào)用關(guān)系過于復(fù)雜,實(shí)在難以搞清楚某個(gè)對象究竟是否已經(jīng)釋放了內(nèi)存,此時(shí)應(yīng)該重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),從根本上解決對象管理的混亂局面。

              (2)函數(shù)的return語句寫錯(cuò)了,注意不要返回指向“棧內(nèi)存”的“指針”或者“引用”,因?yàn)樵搩?nèi)存在函數(shù)體結(jié)束時(shí)被自動(dòng)銷毀。

              (3)使用free或delete釋放了內(nèi)存后,沒有將指針設(shè)置為NULL。導(dǎo)致產(chǎn)生“野指針”。

                【規(guī)則1】用malloc或new申請內(nèi)存之后,應(yīng)該立即檢查指針值是否為NULL。防止使用指針值為NULL的內(nèi)存。

                  【規(guī)則2】不要忘記為數(shù)組和動(dòng)態(tài)內(nèi)存賦初值。防止將未被初始化的內(nèi)存作為右值使用。

               【規(guī)則3】避免數(shù)組或指針的下標(biāo)越界,特別要當(dāng)心發(fā)生“多1”或者“少1”操作。

                【規(guī)則4】動(dòng)態(tài)內(nèi)存的申請與釋放必須配對,防止內(nèi)存泄漏。

              【規(guī)則5】用free或delete釋放了內(nèi)存之后,立即將指針設(shè)置為NULL,防止產(chǎn)生“野指針”。

          4. posted on 2011-02-11 00:22 Geek.tan 閱讀(495) 評論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            導(dǎo)航

            統(tǒng)計(jì)

            公告

            coding是我的寂寞,我是誰的寂寞

            隨筆分類(40)

            隨筆檔案(48)

            搜索

            積分與排名

            最新評論

            評論排行榜

            欧美久久一区二区三区| 人妻无码αv中文字幕久久琪琪布| 99久久婷婷国产综合亚洲| 91久久精品91久久性色| 欧美综合天天夜夜久久| 亚洲国产一成久久精品国产成人综合| 久久国产免费直播| 亚洲国产精品热久久| 欧美久久久久久| 精品国产综合区久久久久久 | 香蕉久久一区二区不卡无毒影院| 久久国产成人午夜aⅴ影院| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 亚洲成色www久久网站夜月| 久久噜噜电影你懂的| 国产成年无码久久久免费| 精品久久久久久国产三级| 久久精品夜夜夜夜夜久久| 日韩一区二区三区视频久久| 国产精品久久波多野结衣| 久久精品青青草原伊人| 久久九九久精品国产| 一级做a爰片久久毛片人呢| 亚洲午夜久久久久久久久久| 久久综合成人网| 久久久久亚洲AV无码专区网站| 久久婷婷综合中文字幕| 久久久久久夜精品精品免费啦| 99精品国产免费久久久久久下载| 99久久国产热无码精品免费久久久久| 久久久久久国产精品免费无码| 久久www免费人成看片| 国产精品久久久久久久人人看 | 欧美精品乱码99久久蜜桃| 久久只这里是精品66| 久久亚洲国产精品五月天婷| 久久久久久国产精品美女| 欧美麻豆久久久久久中文| 久久久精品久久久久久 | 91久久九九无码成人网站| 国产成人无码久久久精品一|