堆和栈【翻译】

看到一篇比较有意思的文章,在这里就翻译一下,当今天发表的内容了。

from http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/

一个程序对于内存的使用,一般可以分为四类:

1. 代码区域,通过的编译的程序在代码中存储的位置

2. 全局变量区域,全局变量存储的位置

3. 堆,动态内存分配的变量存储的位置

4. 栈,函数参数和局部变量存储的位置

下面将主要针对3,4两个方面进行论述。

 

堆是一个用于动态分配的很大的内存池。在C++中,当你使用new操作符分配内存时,这个内存是从堆中取得的。

   1: int *pValue = new int; // pValue is assigned 4 bytes from the heap
   2: int *pArray = new int[10]; // pArray is assigned 40 bytes from the heap

因为,要分配的内存的准确位置事先是不知道的,所以分配的内存是间接获取的,也就说明了为什么new操作符返回的是指针。这里你并不需要担心背后内存具体如何分配的机制。但是,有一点值得明了,连续的内存请求所指向的很可能不是连续的地址的内存片段。如:

   1: int *pValue1 = new int;
   2: int *pValue2 = new int;
   3: // pValue1 and pValue2 may not have sequential addresses

上例中,两个new是连续的,但是分配得到的pValue1和pValue2的地址是不连续的。当动态分配的变量被删除后,内存有被返回到堆中以备后续中再次被动态分配。

堆有如下优缺点:

1. 分配的内存一直处于被分配的状态,知道去分配操作出现,才回到初始状态(没有及时去分配,如new后没有用delete,会导致内存的泄漏)。

2. 动态分配的内存必须通过指针联系

3. 由于堆是一个很大的内存池,大的数组,结构,类都应该在这里分配得到内存

 

栈调用扮演了一个很有趣的角色。在我们讨论栈调用之前,让我们讨论一下什么叫做栈。

想象一下自助餐厅中的一堆叠起来的盘子。因为每个盘子都比较重,它们被叠起来的,你只能做以下三件事情。

1)看向最上面的盘子

2)将最上面的盘子拿掉

3)在上面放一个新的盘子

在计算机编程中,栈是一个存储其他变量的容器(很像一个数组)。但是,一个数组能够以你想要的方式任意更改获取其中的元素,栈则有更多的限制,栈中能够进行的操作如下:

1)查看栈顶的项

2)将栈顶的项从顶部移除

3)将一个新的项放置顶部

栈是后进先出(LIFO)的数据结构。

(略掉一些内容······)

我们主要来看当调用函数是栈发生了一些什么行为。

1)发生函数调用处的相关指令的地址被push进栈中

2)函数返回类型置于栈中,设置一个占位符

3)CPU跳至函数的代码中

4)现在栈顶的内容是一个特殊指针,栈帧。随后所有的加入到栈中的内容都是该函数的局部信息。

5)所有的函数参数都被放入栈中

6)函数中的指令得到执行

7)函数中的局部变量push栈中

当函数结束的时候,发生如下事件:

1)函数的返回值拷贝进入一个占位符中,

2)在栈帧之后的所有内容都被pop off,所有的局部变量都被销毁

3)返回值被pop off并赋值给函数中的变量,如果调用函数的返回值没有赋值给任何东西,该值就会丢失

4)下一个语句的地址从栈中pop off,CPU继续执行

 

栈溢出

栈的大小是有限的,只能有序的容纳一定量的信息。如果程序试图向栈中放入过多的信息,栈将会溢出。栈溢出发生在栈的内存都被分配完了,那种情况下,更多的分配,将会发生在内存的其它片段中。

栈溢出通常发生在分配了太多的变量到栈上,或太多的嵌套函数调用,导致结果就是程序的奔溃。

如:

   1: int main()
   2: {
   3:     int nStack[100000000];
   4:     return 0;
   5: }

栈的优缺点:

* 栈中的内容可以一直保留到pop off发生

* 编译时,栈中分配的内存是已知的,因此,可以直接通过变量访问内存。

* 因为栈相对而言是比较小的,所以小心会吃掉很多栈空间的事情。包括大型数组,结构体,类过多的内嵌,过多的递归等。

posted on 2012-05-27 23:08 钟谢伟 阅读(1838) 评论(3)  编辑 收藏 引用

评论

# re: 堆和栈【翻译】 2012-05-28 08:40 tb

一直认为是进和出的关系   回复  更多评论   

# re: 堆和栈【翻译】 2012-06-17 23:31 nonoob

在函数调用时设置的占位符是返回值类型的指针还是返回值本身?  回复  更多评论   

# re: 堆和栈【翻译】 2012-06-18 17:36 钟谢伟

@nonoob
我觉得,可能是在内存中预留出1个具有返回值大小的空间,然后在栈中保留该空间的地址??----猜测,不知道怎么跟踪代码查看详情,额  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2012年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(1)

随笔档案

IT网站

My Friends

搜索

最新评论

阅读排行榜

评论排行榜