关于堆和栈

1.栈和堆有什么区别

  •  我们可从4G的地址空间上看,他们完全不同的两块内存。栈是由系统开辟,系统释放。堆是由人为开辟,人为释放。栈是由C语言中的malloc/free开辟释和放,堆是由C++中的new/delete开辟和释放。因为堆是由人员分配管理的,所以很有可能造成内存泄漏。
  • 栈的开辟释放效率快,申请的内存是连续的。堆申请的内存不一定连续,相对于栈效率低。堆容易产生内存碎片,灵活度高。
  • 栈是由高地址向低地址扩展的连续内存,堆是低地址向高地址扩展的非连续内存。在window下,栈的大小默认为1M;linux系统下,栈的大小为2M或10M(可通过ulimit-s查看)。堆的大小和虚拟内存的大小有关。

2.栈和堆的大小,申请一个整形数组最大可以达到多大(在不同版本下)

   我们常用的版本分为linux和window系统,栈和堆的大小跟以下几个因素有关:

  1. 当前系统的虚拟地址空间大小,用户和内核空间划分比例
  2. 实际物理内存的大小
  3. 当前系统交换分区(虚拟内存)的大小       

    系统默认栈的大小为10M。当我开辟大于10M大小的时候还是会开辟成功,但是还会出现段异常错误。堆或者栈在开辟内存是都只是在虚拟地址空间上分配内存,当进行读写操作时,伴随着缺页异常,然后才进行页面映射和分配真正的物理内存。缺页异常处理函数是do_page_fault,越界访问栈空间,内核会在一定范围内对栈空间扩容。

  堆的大小和当前系统设置的虚拟大小有关。在我们分配内存时,并没有分配真正的物理内存,只有在读取或写数据时才会出现缺页异常,才会真正分配物理内存和进行页面映射。在分配内存时,会有页面置换操作。根据LRU算法,把不经常使用的页面换到交换区中,腾出更多内存给进程使用。交换区不宜过多,而且他的读写效率低,过多依赖交换分区,会导致系统运行效率下降。所以堆的大小与当前系统物理内存大小、交换分区大小息息相关。因为他们都属于用户空间部分。

  在window下4G虚拟地址空间的分配比例为2:2(比例可修改),linux系统下为1:3。因此堆在linux下的大小要大于在window是下的大小。

3.4G虚拟地址内存空间及变量

                                 关于堆和栈

    linux内核空间给每一个进程分配了4G大小的虚拟地址空间,3G用户空间和1G内核空间。

  •   全局变量已初始化但初始化不为0的变量存储在 .data段
  •   全局变量未初始化且初始化为0的变量存储在  .bss段
  •   局部变量在栈上存储
  •   常量字符串在 .rodata段存储
  •   静态变量在.data段存储

4.内联函数与宏的区别

  •   宏在预编译阶段,字符串替换,没有类型和安全检查;内联函数是在编译阶段,有完整的语句类型检查,有安全性检查。
  •   宏是没有办法调试的;内联函数在debug版本下和普通函数一样,出了问题方便调试。
  •   大量宏代码阅读性降低;内联函数结构清晰,阅读性高。
  •   宏定义函数,替换后还是正常函数调用,有函数调用开销(栈帧开辟和回退);内联函数在编译时期,在函数调用点把函数代码直接展开,省了函数调用开销,代码运行效率高。