电脑内(nèi)存(cún)整理清理碎片释放器工具软件(jiàn),就是将驻留在内存中(zhōng)的数据从内存中释放出来,以提(tí)高系统内存资源的利用率,进(jìn)而提升系(xì)统性能。 在(zài)C++中,内存分成5个区,他们分别是堆、栈、自(zì)由存储区、全局/静态(tài)存储(chǔ)区和常量存储区。内存中,堆和栈的区别:1、管理方式(shì)不同; 2、空间大小不同; 3、能否产(chǎn)生(shēng)碎片不同; 4、生长方向不同; 5、分(fèn)配方式不同; 6、分配效率不同。
五大(dà)内存(cún)分区
在C++中(zhōng),内(nèi)存分成5个区,他们分别是(shì)堆、栈、自由存(cún)储区(qū)、全局/静态(tài)存储区(qū)和常(cháng)量(liàng)存储区。
栈,就是那些由编译器在需(xū)要的时候分配,在不需要(yào)的时候自动清除的(de)变(biàn)量(liàng)的存储区。里面的变量通(tōng)常(cháng)是(shì)局部变量、函数(shù)参数等。
堆,就是那些由new分配的内存块,他们的释放编译器不去管(guǎn),由我们的应用程(chéng)序去控制,一般一个new就要对(duì)应一个delete。如(rú)果程序(xù)员没有释(shì)放掉,那么(me)在(zài)程序(xù)结束后,操作系统会自动回收。
自由(yóu)存(cún)储区,就是(shì)那些由(yóu)malloc等分配的内存(cún)块,他和堆是(shì)十分相似的,不过它是用free来结束自己的生命(mìng)的(de)。
全局/静态存储区,全局变量和静态变量(liàng)被分配(pèi)到同(tóng)一块(kuài)内存(cún)中,在以前的C语言中,全局变量又分为初始化的和(hé)未(wèi)初始化的,在C++里面没有(yǒu)这个区分了,他们共同占用同一块(kuài)内存区。
常(cháng)量存储区,这是一(yī)块比较特殊的存储区,他们里面存放的是常量,不允许(xǔ)修改(当然,你要通过非正当手段也可以修改(gǎi),而(ér)且方法(fǎ)很多)
内存(cún)中,堆和栈的(de)区别
初学内(nèi)存的(de)时候,免(miǎn)不了(le)对堆和栈的(de)学(xué)习了(le)解。很多初学(xué)者对(duì)这(zhè)一问题都很(hěn)敏感!甚至一些(xiē)“老手”对(duì)这一问题也有一些疑问。搞清(qīng)楚堆区和栈区的区(qū)别,是我们学习,了解内存并(bìng)进一步(bù)应用的必经(jīng)阶段!
主要的区别由以下(xià)几点:
1、管理方式不同;
2、空间大小(xiǎo)不同;
3、能否产(chǎn)生(shēng)碎(suì)片不同;
4、生长方向(xiàng)不同;
5、分(fèn)配方式不同;
6、分(fèn)配效率(lǜ)不同;
管(guǎn)理方(fāng)式:对于栈(zhàn)来讲,是由编译器自(zì)动(dòng)管理,无需我(wǒ)们(men)手工控制(zhì);对(duì)于(yú)堆(duī)来说,释放工作由程(chéng)序员控制,容易产(chǎn)生memory leak。
空间大小:一般来(lái)讲在32位系统下,堆(duī)内存可以达到4G的空(kōng)间,从这个(gè)角度来看堆(duī)内存几乎是(shì)没(méi)有(yǒu)什么(me)限(xiàn)制的(de)。但是对(duì)于栈来讲,一般都是(shì)有一定的空(kōng)间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不(bú)清(qīng)楚(chǔ)了)。当然,我(wǒ)们(men)可以(yǐ)修改:
打开工程,依次操作菜单(dān)如下:Project->Setting->Link,在Category 中(zhōng)选中Output,然后在Reserve中设定堆栈的最大值和commit。
注意:reserve最小(xiǎo)值为4Byte;commit是(shì)保留在虚拟内存(cún)的(de)页(yè)文件里面,它设置的较大会使(shǐ)栈(zhàn)开辟较大的值,可能增加内存的开销和(hé)启(qǐ)动时间。
碎片问(wèn)题:对(duì)于(yú)堆(duī)来讲,频繁的new/delete势必(bì)会造成(chéng)内存(cún)空间的不连续,从而造成大量的碎(suì)片(piàn),使(shǐ)程序效率降(jiàng)低。对于栈来讲(jiǎng),则不会(huì)存在这个(gè)问题,因为栈是先进后出的队列,他们是如此的一一对(duì)应,以至于(yú)永(yǒng)远都不可能(néng)有一个(gè)内存(cún)块从栈中间(jiān)弹(dàn)出,在他弹出(chū)之前,在他上面的(de)后进的栈内容(róng)已经被弹出,详细的可以参考数据结构,这(zhè)里我们就不再一一讨论了(le)。
生长方向:对(duì)于堆来讲,生长方向是(shì)向(xiàng)上(shàng)的,也就是向着内存地址增(zēng)加(jiā)的方向;对于栈(zhàn)来讲,它的生长方向是向下的,是向着内存地址减(jiǎn)小(xiǎo)的方向(xiàng)增(zēng)长。
分配方式:堆都是动态分配的,没(méi)有静态分配的堆(duī)。栈有2种分配方式:静态分配和动态分配。静态分配是(shì)编译器(qì)完成的,比如局部变量的分(fèn)配。动态分配由alloca函数进行(háng)分(fèn)配,但是栈的动态(tài)分(fèn)配和堆是不同的(de),他的动态(tài)分配(pèi)是由编译器进行释放(fàng),无需我们手工实(shí)现。
分配效率:栈是机(jī)器系统(tǒng)提供的数据结构,计(jì)算机会在底(dǐ)层对栈提供支持:分配专门的寄存器存放栈的地址,压(yā)栈出栈(zhàn)都有专门的指(zhǐ)令执行,这就决定(dìng)了(le)栈的(de)效率比较(jiào)高。堆则是C/C++函数库提(tí)供的,它的机制是很(hěn)复杂的,例如为(wéi)了分配一块内存(cún),库函数会按照一定的(de)算(suàn)法(具(jù)体的算(suàn)法可以参考数据结构/操作系统(tǒng))在堆(duī)内存中搜索(suǒ)可用的足够大小的空间(jiān),如果没(méi)有(yǒu)足够大小的空间(可能是由于内存碎(suì)片太多),就有可能调用系统功能去增加程序数据段的(de)内存(cún)空间,这(zhè)样就有机会(huì)分到足够(gòu)大小的内存,然后进行(háng)返回(huí)。显然,堆(duī)的效率比(bǐ)栈要低得(dé)多。
从这里(lǐ)我们(men)可以看到,堆(duī)和栈(zhàn)相比,由于大量new/delete的(de)使用,容易造成大量的内存碎片;由(yóu)于没有专门的系统支(zhī)持(chí),效率很低;由于可能引发用(yòng)户态和核心态(tài)的切换,内(nèi)存的申请,代价(jià)变得更加昂贵。所以(yǐ)栈在程序中是应用(yòng)最广泛(fàn)的,就(jiù)算(suàn)是函数的调用也利用栈去完(wán)成,函数调用过程中的参数,返回(huí)地址(zhǐ),EBP和(hé)局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。
虽然(rán)栈(zhàn)有(yǒu)如此众多的好处,但是由于(yú)和堆相(xiàng)比不是那么(me)灵活,有时候分配大量的内存空间,还(hái)是用堆好一些。
无论是堆还是(shì)栈(zhàn),都要防止(zhǐ)越界(jiè)现象的发生(shēng)(除非你是(shì)故意使其越界),因为越(yuè)界的结果(guǒ)要么(me)是程(chéng)序崩溃,要么(me)是摧毁程序的堆(duī)、栈结构,产生以想不到的结果,就算(suàn)是在你的程序(xù)运行过程中(zhōng),没有发生(shēng)上面的问题,你还是要(yào)小心,说不定什么时候就崩掉,那时候debug可是相(xiàng)当困难的!
因此,在构建(jiàn)程序(xù)的时候(hòu)防止越(yuè)界现(xiàn)象的发生,让(ràng)你的程序(xù)更(gèng)健(jiàn)康(kāng)!
