笔试题集锦----内存分配种类

有关存储区的分配 ,C和C++是略有不同的。先来说说C的存储区

 

C的存储区分配划分

  1、栈。由编译器自动分配释放,比如局部变量、函数参数、返回数据以及返回地址等等。

  2、堆。由程序员分配释放,若程序员不释放,程序结束时由OS回收。分配方式类似于链表。

  3、全局区(静态存储区)。这里存储的是全局变量以及静态变量。不过初始化的全局变量和静态变量存在一块区域内,未初始化的放到另一块区域内。程序结束时释放

  4、文字常量区。这里存储的是一些常量,在程序结束的时候释放。

  下面是配合例子说明内存分配的划分

int a = 0;//全局存储区,已初始化
char *pName;//全局存储区,未初始化

void FuncA()
{
    int a;    //
    char name[] = "abcde";//
    char *pNumber = "12345";    //pNumber存储在栈上,"12345"在文字常量区
    static int b =2;    //全局区(静态存储区,已经初始化)
}

 

 C++的存储区分配划分

(1)堆。

  堆上的内存通常编译器不负责处理这块内存,由程序来控制。这里的内存由new来分配,用delete释放。如果忘记delete会引起内存泄漏,但是程序结束后操作系统会自动回收

  例如 int *p = new int[5];

  首先在堆上申请了存储5个int的数组,然后在栈上申请内存存储指针p,就是说在栈内存中存放了一个指向一块堆内存的指针p。如果释放这些内存呢?栈上的内存我们不用关心,编译器会自动处理,那在堆上申请的内存呢?delete p?p指向数组的首地址,也就是数组第一个变量的地址,所以delete p只删除了数组第一个变量的内存,并不能释放整个数组的内存,所以要delete []p,也就是说告诉编译器删除整个数组。

(2)栈。

  栈上的内存由编译器直接负责处理,在编译器需要的时候就分配,不需要的时候就自动释放。例如函数的参数、局部变量等。

(3)自由存储区。

  由malloc分配的内存,类似堆,但是释放由free完成。

  自由存储区和堆并不完全是一回事,感兴趣的可以看这篇文章的分析  https://www.cnblogs.com/QG-whz/p/5060894.html

(4)全局/静态存储区。

  全局变量和静态变量都放在这块内存中,这里的变量都会自动初始化。

(5)常量存储区。

  这里面存储的是常量,理论上不允许修改。

 

下面说说不同存储区之间的差别

1、堆与栈

  分配方式不同

  空间大小不同

  管理的方式不同

  分配的效率不同

  能否产生碎片不同

  生长方向不同

  分配方式:堆是动态分配的,没有静态分配。而栈分静态和动态分配两种方式。栈的静态分配由编译器完成,比如局部变量的分配;栈的动态分配由alloca函数进行分配,释放由编译器自动完成。

  空间大小:在32位系统下,堆内存理论上可分配4G(2^32)大小,栈能分配的内存都是有限的,一般为几M。

  管理方式:堆的申请和释放通过程序控制,如果不及时的释放就会造成内存泄漏(memory leak);而栈是由编译器自动处理的,无需我么们关心。

  分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供专门的支持--设置专门的寄存器存放栈的地址,压栈出栈都会有专门的指令去完成,这就决定了栈的效率比较高。而堆是由C++函数库提供的,分配的方式比较复杂,比如在分配一块内存时,首先通过相应的算法在堆中搜索可用的足够大的空间,如果没有足够大的空间,就会调用系统函数去增加堆的空间,这样才能分配到足够大的空间,然后返回。因此堆的效率就比较低。

  碎片的产生:堆的频繁new/delete势必会造成内存的不连续,从而造成大量的碎片,使程序的效率变低;但是栈不同,栈是先进后出,所以不可能有内存从栈的中间跳出,因此它的内存都是连续的,效率也就较高。

  生长方向:堆是向上增长的,也就是内存地址增长的方向;栈是向下的,是往地址减小的方向。

 

参考http://www.cnblogs.com/hanyonglu/archive/2011/04/12/2014212.html

posted @ 2017-08-01 01:04  Qt王二狗  阅读(518)  评论(0)    收藏  举报