20169215《Linux内核原理与分析》第三周作业
内存中的堆与栈
在本科学习数据结构的时候,我们学过两种数据结构:堆和栈。
栈就像一个存放数据的桶,后进先出;堆是一种经过排序的树形结构,每个结点都有一个值,其根结点的值最大(最小),根结点的两棵子树也是堆。
但是经过上一周的学习,我发现系统内存中分配的堆和栈与本科时学习的数据结构的堆栈有点不同,于是就查询了一些资料,从而了解内存分配中的堆和栈。
C语言程序内存分配中的堆栈
堆栈是高级语言的基础,它是C语言运行时必须的一个记录调用路径和参数的空间,其作用有:函数调用框架、传递参数、保存返回地址、提供局部变量等等。
内存中的栈区处于相对较高的地址,一般来说栈的是向低地址增长的,即每次入栈操作都会使栈顶指针指向的地址减4(32位系统)。栈中分配局部变量空间。
堆区是向上增长的用于分配程序员动态申请的内存空间。
此外还有用于分配静态变量、全局变量的静态区;分配常量和程序代码空间的只读区;等等。
在查找资料学习过程中,我发现很多人都用了个经典的例子,分享一下:
int a = 0; \\\全局初始化区
char *p1; \\\全局未初始化区
main()
{
int b; \\\栈
char s[] = "abc"; \\\栈
char *p2; \\\栈
char *p3 = "123456"; \\\123456\0在常量区,p3在栈上
static int c =0; \\\全局(静态)初始化区
p1 = (char *)malloc(10); \\\堆
p2 = (char *)malloc(20); \\\堆
}
从上面例子,我们可以分析出很多结论:
- 存储的变量不同:栈用于分配局部变量空间,堆用于分配动态申请的内存空间,静态区分配静态变量和全局变量;
- 内存申请和释放的方式不同:栈分配空间是系统自动的,栈的大小是系统固定好的,每次压栈分配的空间大小也是固定的;而堆分配空间则相对较随意,因为堆是通过遍历操作系统的一个记录空闲内存地址的链表,从而找到第一块空间大于所申请空间的堆结点,然后删除该空闲结点,分配所申请大小的空间并把多余的空闲空间重新加入空闲内存地址链表,由此可见堆得空间不连续,分配空间大小也很随意;释放内存时,栈只需要把栈顶指针移动即可,而堆所分配的空间必须通过delete语句才能正确释放内存;
- 分配速度不同:显而易见,栈通过系统分配空间,速度肯定快,是程序员自身无法控制;堆分配空间通过动态申请,速度要慢点,而且容易产生内存碎片,好在它的灵活性弥补了速度慢的缺点。
- 存取效率不同:栈中存放的变量是在运行时才进行赋值的,而堆中存放的变量在编译时就已经赋值。但是在之后的重新赋值中,栈上的变量效率要明显高于指针指向的变量(如栈)。
参考资料
1、《内存堆和栈的区别》http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
2、《C语言堆栈入门——堆和栈的区别》http://blog.chinaunix.net/uid-26696487-id-3513255.html