首页 > 其他分享 >5.堆和栈的区别

5.堆和栈的区别

时间:2023-07-03 21:25:29浏览次数:27  
标签:区别 申请 系统 链表 内存 空间 分配

  • 申请方式不同。
    • 栈由系统自动分配。
  • 堆是自己申请和释放的。
  • 申请大小限制不同。
    • 栈顶和栈底是之前预设好的,栈是向栈底扩展,大小固定,可以通过ulimit -a查看,由ulimit -s修改。
    • 堆向高地址扩展,是不连续的内存区域,大小可以灵活调整。
  • 申请效率不同。
    • 栈由系统分配,速度快,不会有碎片。
    • 堆由程序员分配,速度慢,且会有碎片。

栈空间默认是4M, 堆区一般是 1G - 4G

管理方式 堆中资源由程序员控制(容易产生memory leak) 栈资源由编译器自动管理,无需手工控制
内存管理机制 系统有一个记录空闲内存地址的链表,当系统收到程序申请时,遍历该链表,寻找第一个空间大于申请空间的堆结点,删除空闲结点链表中的该结点,并将该结点空间分配给程序(大多数系统会在这块内存空间首地址记录本次分配的大小,这样delete才能正确释放本内存空间,另外系统会将多余的部分重新放入空闲链表中) 只要栈的剩余空间大于所申请空间,系统为程序提供内存,否则报异常提示栈溢出。(这一块理解一下链表和队列的区别,不连续空间和连续空间的区别,应该就比较好理解这两种机制的区别了)
空间大小 堆是不连续的内存区域(因为系统是用链表来存储空闲内存地址,自然不是连续的),堆大小受限于计算机系统中有效的虚拟内存(32bit 系统理论上是4G),所以堆的空间比较灵活,比较大 栈是一块连续的内存区域,大小是操作系统预定好的,windows下栈大小是2M(也有是1M,在编译时确定,VC中可设置)
碎片问题 对于堆,频繁的new/delete会造成大量碎片,使程序效率降低 对于栈,它是有点类似于数据结构上的一个先进后出的栈,进出一一对应,不会产生碎片。(看到这里我突然明白了为什么面试官在问我堆和栈的区别之前先问了我栈和队列的区别)
生长方向 堆向上,向高地址方向增长。 栈向下,向低地址方向增长。
分配方式 堆都是动态分配(没有静态分配的堆) 栈有静态分配和动态分配,静态分配由编译器完成(如局部变量分配),动态分配由alloca函数分配,但栈的动态分配的资源由编译器进行释放,无需程序员实现。
分配效率 堆由C/C++函数库提供,机制很复杂。所以堆的效率比栈低很多。 栈是其系统提供的数据结构,计算机在底层对栈提供支持,分配专门寄存器存放栈地址,栈操作有专门指令。

形象的比喻

  栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。

  堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

参考资料来源:

阿秀

标签:区别,申请,系统,链表,内存,空间,分配
From: https://www.cnblogs.com/codemagiciant/p/17524078.html

相关文章

  • 7.区别以下指针类型?
    int*p[10]int(*p)[10]int*p(int)int(*p)(int)int*p[10]表示指针数组,强调数组概念,是一个数组变量,数组大小为10,数组内每个元素都是指向int类型的指针变量。int(*p)[10]表示数组指针,强调是指针,只有一个变量,是指针类型,不过指向的是一个int类型的数组,这个数组大小是10。i......
  • 10.malloc和new的区别?
    malloc和free是标准库函数,支持覆盖;new和delete是运算符,支持重载。malloc仅仅分配内存空间,free仅仅回收空间,不具备调用构造函数和析构函数功能,用malloc分配空间存储类的对象存在风险;new和delete除了分配回收功能外,还会调用构造函数和析构函数。malloc和free返回的是void类型指针......
  • 13.宏定义和函数有何区别?
    宏在预处理阶段完成替换,之后被替换的文本参与编译,相当于直接插入了代码,运行时不存在函数调用,执行起来更快;函数调用在运行时需要跳转到具体调用函数。宏定义属于在结构中插入代码,没有返回值;函数调用具有返回值。宏定义参数没有类型,不进行类型检查;函数参数具有类型,需要检查类型。......
  • 14.宏定义和typedef区别?
    宏主要用于定义常量及书写复杂的内容;typedef主要用于定义类型别名。宏替换发生在编译阶段之前,属于文本插入替换;typedef是编译的一部分。宏不检查类型;typedef会检查数据类型。宏不是语句,不在在最后加分号;typedef是语句,要加分号标识结束。注意对指针的操作,typedefchar*p_cha......
  • /etc/profile 和 ~/.bashrc的区别
    /etc/profile和~/.bashrc是两个不同的文件,它们在环境变量设置和启动脚本方面扮演着不同的角色。/etc/profile:/etc/profile是系统级别的配置文件,用于设置全局的环境变量和执行系统范围的初始化命令。当登录到系统时,会首先读取/etc/profile文件来加载系统的环境变......
  • flask run 和python xxx 两种方式的区别
    在Flask项目中,flaskrun和pythonxxx(其中xxx是Python文件名)是两种不同的方式来运行Flask应用程序。flaskrun:这是Flask提供的命令行工具,用于在开发环境中运行Flask应用程序。当你在项目目录下运行flaskrun命令时,Flask会自动检测应用程序的入口文件(通常是app......
  • Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别
    有个需要是需要在安装包安装初始化时安装MicrosoftVisualc++2013Redistributable也就是判断软件安装前需不需要运行vcredist_x64.exe和VC_redist.x64.exe这两个程序第一反应就是可以通过注册表判断是否已经安装过环境但测试发现需求的两个版本不同,注册表位置竟然也不......
  • 什么是SPI,和API有啥区别
    SPI代表服务提供者接口(ServiceProviderInterface),是一种Java编程语言的编程规范。它定义了一组接口或类的规范,供第三方开发人员实现,以向应用程序提供特定的服务或功能。SPI侧重于接口的定义和实现者的开发。API代表应用程序编程接口(ApplicationProgrammingInterface),是一组预定......
  • PG在转换null值时,需要注意 CASE WHEN与 COALESCE 的区别
    目录适用范围方案概述实施步骤在ORACLE测试如下在Postgresql测试如下总结参考文档适用范围any方案概述在把ORACLE迁移到PG过程中,我们经常需要转换ORACLE的DECODE,但是如果将更DECODE(C,NULL,0,C)进行转换的话,我们可以选择用CASEWHEN或COALESCE两种方案;但如果是DEC......
  • java中的BO根DTO的区别以及使用场景
    java中的BO根DTO的区别以及使用场景  BO(BusinessObject)业务对象BO就是PO(PersistantObject)的组合简单的例子比如说PO是一条交易记录,BO是一个人全部的交易记录集合对象复杂点儿的例子PO1是交易记录,PO2是登录记录,PO3是商品浏览记录,PO4是添加购物车记录,PO5是搜索记录,BO是个......