1.32位Linux系统中每个进程的虚拟地址空间
有.text,.data,.bss,堆,栈,命令行参数,环境变量等。堆是存储动态分配内存,栈是存储的是局部变量、函数参数、返回地址等。
堆中的内容是匿名的,不能按名字直接访问,只能通过指针间接访问,要内存对齐,可通过系统调用brk()和sbrk()来移动break指针扩张堆,一般是系统自动调用。栈三个用途:1.为函数内部声明的非静态局部变量提供存储空间,2.记录函数调用过程中相关维护信息,3.临时存储区。栈会动态增长,超过设置的最大值会栈溢出,程序出现段错误。
2.管理方式
栈是由编译器自动管理,以函数为单位进行栈分配,函数栈帧、局部变量、形参变量等都在栈上。
堆是由用户自己管理,使用方便,但容易产生内存泄漏。
3.生长方式空间大小
栈是由高地址向低地址扩展的连续内存,一般大小2M或者10M(可以通过ulimit -s查看)。
堆是由低地址向高地址扩展的非连续的内存,堆大小影响因素较多,和系统的虚拟内存的大小有关。
4.存储内容
栈在函数调用时,首先压入主函数中下一条指令(函数调用语句的下一条可执行语句)的地址,然后时被调用函数的局部变量。调用结束后,局部变量先出栈,然后时参数,最后栈顶指针指向最开始存的指令地址(函数调用语句的下一条可执行语句)。
堆通常在头部用一个字节存放大小,存放内容由用户决定。
5.分配效率
栈是由计算机底层提供支持,分配专门的寄存器存放栈地址,入栈出栈由战门的指令执行,效率较高。
堆是由函数库提供,机制复杂,效率低。
6.分配后的系统响应
只要栈的剩余空间大于所申请的空间,系统将会位程序提供内存,否则栈溢出。系统为堆维护一个记录空闲内存地址的链表。
收到内存分配的请求,会便利该链表寻找第一个空间大于申请的堆结点,然后将该节点从空余结点链表删除,如果没有足够空间,有可能会调用系统调用增加。
在数据结构上的栈是一个先进后出的结构,底层是用deque实现的,堆分为大根堆和小根堆,经常用于排序,堆排序的时间复杂度是O(logn),查找前k个最大值或者最小值,建堆的时间复杂度O(n),插入、查找和调整堆的时间复杂度O(logn)。