内存中堆和栈

  1. 栈是机器系统提供的数据结构, 现代计算机(串行执行机制)都直接在代码底层支持栈的数据结构, 有专门的寄存器指向栈所在的地址, 有专门的机器指令完成数据入栈出栈的操作
  2. 栈的特点是效率高, 支持的数据类型有限, 一般是整数, 指针, 浮点数等系统直接支持的数据类型, 并不直接支持其他的数据结构
  3. 子程序的调用就是直接利用栈完成的, 机器的 call 指令里隐含了把返回地址压入栈, 然后跳转至子程序地址的操作, 子程序中的 ret 指令则隐含了从堆栈中弹出返回地址并跳转到返回地址的操作
  4. C/C++ 程序中的自动变量存入栈中, 这也就是为什么当函数返回时, 该函数的自动变量自动失效的原因
  5. 栈的特点: 快速, 高效, 但有限制, 数据不灵活, 对于进程/线程是唯一的
  6. 栈空间分静态分配和动态分配两种: 静态分配是编译器完成的, 比如自动变量(auto), 动态分配由 alloca 函数完成, 均自动释放, 也就没有释放函数, 为可移植的程序起见, 栈的动态分配操作是不被鼓励的
  7. 函数调用时会在栈上有一系列的保留现场及传递参数的操作, 当一个函数调用完返回后它会释放该函数中所有的栈空间, 栈的存储地址连续, 不会产生内存碎片
  8. 栈的空间大小有限定, vc 中的缺省是2MB, 栈不够用的情况一般是程序中分配了大量数组或递归函数层次太深
  9. 栈是先入后出的数据结构, 一般是由高地址向低地址方向生长
  10. 栈使用的是一级缓存, 通常被调用时处于存储空间中, 调用完毕立即释放

  1. 堆是由 C/C++ 函数库提供的, 并不是由系统(无论是机器系统还是操作系统)支持的
  2. C中的 malloc, free 函数或C++中的 new, delete 函数维护了一套内部的堆数据结构
  3. 动态内存的分配: 先从内部堆中寻找可用的内存, 若失败则利用系统调用来动态增加程序数据段的内存大小, 新分配得到的内存首先被组织进内部堆中去, 然后再以适当的形式返回给调用者
  4. 动态内存的释放: 内存被返回内部堆结构中, 且可能会被适当的处理, 比如和其他空闲空间合并成更大的空闲空间, 以更适合下一次内存分配
  5. 堆的特点: 灵活, 方便, 数据适应面广泛, 但由于堆中的数据需要通过指针进行存取, 效率低, 对于进程/线程不一定唯一, 不同堆分配的内存无法互相操作
  6. 堆空间的分配总是动态的, 虽然程序结束时, 所有的数据空间都会被操作系统回收, 但是精确的内存申请/释放匹配是良好程序的基本要素, 否则可能产生内存泄漏
  7. 频繁地调用 malloc 和 free 会产生内存碎片, 因为 C 分配动态内存时是寻找匹配的内存的
  8. 堆内存区的地址是不连续的, 它是系统将空闲内存块链接起来的链表, 用户用 new/malloc 请求分配时, 找到第一个满足大小要求的块从链表中删除此节点, 然后分给用户
  9. 堆的数据结构可以被看成是一棵树, 如堆排序
  10. 堆存放在二级缓存中, 生命周期由虚拟机的垃圾回收算法来决定, 并不是一旦成为孤儿对象就能被回收, 所以调用这些对象的速度要相对来得慢一些

内存分配机制实际上相当于一个内存分配的缓冲池(Cache), 使用这套机制有如下若干原因:

  1. 系统调用可能不支持任意大小的内存分配, 有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配), 这样对于大量的小内存分配来说会造成浪费
  2. 系统调用申请内存可能是代价昂贵的, 可能涉及用户态和内核态的转换
  3. 随意的内存分配和释放操作会造成内存碎片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值