0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是堆内存与栈内存?它们的分配和回收有什么特点?

xCb1_yikoulinux 来源:程序喵大人 作者:程序喵大人 2022-07-01 10:33 次阅读

这篇文章分享一个面试中经常被问到的知识点:堆内存和栈内存有什么区别?平时开发应该使用堆内存还是栈内存?

要回答这个问题,我们首先需要知道什么是堆内存,什么是栈内存,它们的分配和回收有什么特点?

先介绍下栈内存:

栈内存是为线程留出的临时空间,每个线程都有一个固定大小的栈空间,而且栈空间存储的数据只能由当前线程访问,所以它是线程安全的。

栈空间的分配和回收是由系统来做的,我们不需要手动控制。

当一个函数调用时,系统就会为该函数的调用分配栈空间,当函数返回后,系统就会自动回收这块空间,同理,下次其它函数调用和返回,系统还是会自动分配和回收空间。

那它是怎么分配和回收的呢?

可以看这两个动画

9455e43c-f75f-11ec-ba43-dac502259ad0.gif

94ae6f6c-f75f-11ec-ba43-dac502259ad0.gif

栈空间的大小是固定的,它有一个水位线,标识栈空间的分配状态,水位线里面的表示已经分配,然后这个水位线会根据函数调用和返回的情况自动调整。

这里可以看到,栈空间的分配和回收非常简单,只需要调整水位线位置就可以了,没有任何多余操作。

那堆内存呢?

我们平时在C语言C++中使用malloc和new分配的内存就是堆内存,堆内存的一大特点就是大小不固定,可以动态扩容,空间由程序员动态分配,更加灵活。

然而,既然有优点也必然伴随着缺点。

第一个缺点就是它容易产生内存泄露,malloc出来的没有free,new出来的如果没有delete,都会产生内存泄露,真正项目内存泄露产生的情况肯定比这个复杂的多。

第二个缺点,容易产生内存碎片,在分配和回收时需要对很多内存碎片进行整理,效率较低,具体可以看这个动画。

94c9bace-f75f-11ec-ba43-dac502259ad0.gif

所以才会有很多自定义的内存分配器,但它肯定还是没有栈空间分配回收速度快。

第三个缺点,线程不安全,它不像栈内存是线程独立的,堆内存可以被一个进程内所有的线程访问,多线程操作就容易产生问题,很多奇奇怪怪的操作就是这么引起的。

那什么变量存储在栈上,什么存储在堆上呢?普通的A a,这种就是都存储在栈上,当使用new和malloc分配的空间会存储在堆上,看这个图:

94ebba7a-f75f-11ec-ba43-dac502259ad0.jpg

new出来的实际空间是在堆上分配,然后在栈上开辟一个指针大小的空间,这个空间有一个指针,指向堆上的那块内存,这样给变量和堆内存之间就关联起来了。

那什么情况下使用栈内存,什么情况下使用堆内存呢?

我整理出来了一个表,贴在这里:

速度
空间管理 高效,不会产生碎片 会产生内存碎片
访问权限 只能局部变量 可以访问全局变量
空间大小限制 操作系统限制 没有特定的限制
内存分配 连续 随机分配
分配和释放 编译器指令自动管理 程序员手动管理
开销
主要问题 空间小 内存碎片
灵活性 固定大小 可以resize

这里可以根据实际需求来决定使用哪类内存。

当然,其实也不用关注那么多,我一般就是大内存使用堆,局部变量小内存使用栈。

这里还涉及到很多其它知识点,比如进程的内存空间布局是怎么样的,栈空间会不会污染、堆内存具体是怎么分配和回收的。

具体在我的公众号里搜索吧,里面有很多相关文章。

原文标题:堆内存和栈内存的区别

文章出处:【微信公众号:一口Linux】欢迎添加关注!文章转载请注明出处。

审核编辑:彭静

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    8

    文章

    2762

    浏览量

    72742
  • C语言
    +关注

    关注

    180

    文章

    7527

    浏览量

    128184
  • 函数
    +关注

    关注

    3

    文章

    3863

    浏览量

    61304

原文标题:堆内存和栈内存的区别

文章出处:【微信号:yikoulinux,微信公众号:一口Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言内存泄漏问题原理

    内存泄漏问题只有在使用堆内存的时候才会出现,栈内存不存在内存泄漏问题,因为栈内存会自动分配和释放
    发表于 03-19 11:38 155次阅读
    C语言<b class='flag-5'>内存</b>泄漏问题原理

    Linux内核内存管理之内核非连续物理内存分配

    我们已经知道,最好将虚拟地址映射到连续页帧,从而更好地利用缓存并实现更低的平均内存访问时间。然而,如果对内存区域的请求并不频繁,那么考虑基于通过连续线性地址访问非连续页帧的分配方案是有意义的。该模式
    的头像 发表于 02-23 09:44 374次阅读
    Linux内核<b class='flag-5'>内存</b>管理之内核非连续物理<b class='flag-5'>内存</b><b class='flag-5'>分配</b>

    Linux内核内存管理之ZONE内存分配

    内核中使用ZONE分配器满足内存分配请求。该分配器必须具有足够的空闲页帧,以便满足各种内存大小请求。
    的头像 发表于 02-21 09:29 408次阅读

    FreeRTOS内存机制详解

    FreeRTOS是一种实时操作系统,它提供了多种内存分配方式,包括动态内存分配和静态内存分配
    的头像 发表于 12-31 16:49 1100次阅读
    FreeRTOS<b class='flag-5'>内存</b>机制详解

    glibc的内存分配回收策略

    Linux内存空间简介 32位Linux平台下进程虚拟地址空间分布如下图: 进程虚拟地址空间分布 图中,0xC0000000开始的最高1G空间是内核地址空间,剩下3G空间是用户态空间。用户态空间
    的头像 发表于 11-13 11:16 342次阅读
    glibc的<b class='flag-5'>内存</b><b class='flag-5'>分配</b><b class='flag-5'>回收</b>策略

    Linux内核的内存管理详解

    内存管理的主要工作就是对物理内存进行组织,然后对物理内存分配回收。但是Linux引入了虚拟地址的概念。
    发表于 08-31 14:46 425次阅读
    Linux内核的<b class='flag-5'>内存</b>管理详解

    如何改进移动系统的内存管理?

    上层应用程序以object为单位进行内存分配回收,而底层内核以page为粒度进行内存管理。这导致系统不了解应用程序内存使用情况,往往直接
    的头像 发表于 07-31 09:13 584次阅读
    如何改进移动系统的<b class='flag-5'>内存</b>管理?

    heap_4内存分配方法介绍

    heap_4 内存分配方法 heap_4 提供了一个最优的匹配算法,不像 heap_2,heap_4 会将内存碎片合并成一个大的可用内存块,它提供了
    的头像 发表于 07-30 10:42 496次阅读

    FreeRTOS heap_3内存分配方法

    heap_3 内存分配方法 这个分配方法是对标准 C 中的函数 malloc()和 free()的简单封装,FreeRTOS 对这两个函数做了线程保护。 heap_3 的特性如下: 1、需要编译器
    的头像 发表于 07-30 10:40 410次阅读
    FreeRTOS heap_3<b class='flag-5'>内存</b><b class='flag-5'>分配</b>方法

    heap_2内存的特性与分配方法

    heap_2 内存分配方法 heap_2 提供了一个更好的分配算法,不像 heap_1那样,heap_2 提供了内存释放函数。heap_2 不会把释放的
    的头像 发表于 07-30 10:36 364次阅读

    heap_1内存分配方法

    [] , 大 小 为configTOTAL_HEAP_SIZE ,这个前面讲 FreeRTOS 配置的时候就讲过了。不管是哪种内存分配方法,它们内存堆都为 ucHeap[],而且大小
    的头像 发表于 07-30 10:33 373次阅读

    使用C语言实现简单动态内存分配

    首先要明白为何需要动态内存分配,熟悉C语言的读者应该对这个比较熟悉,需要一段内存时会使用malloc函数来申请所需要大小的内存,函数返回一段内存
    发表于 07-28 16:26 388次阅读
    使用C语言实现简单动态<b class='flag-5'>内存</b><b class='flag-5'>分配</b>

    关于RTT支持的内存分配算法

    ~ 128k字节之间,分配器会在初始化时根据的大小自动调整。系统中最多包括72种对象的zone,最大能够分配16k的内存空间,如果超出
    发表于 04-27 14:42

    关于RTT支持的内存分配算法

    字节之间,分配器会在初始化时根据的大小自动调整。系统中最多包括72种对象的zone,最大能够分配16k的内存空间,如果超出了16k那么直
    发表于 04-27 14:40

    看看RTThread系统中的内存分配

    任务对外部事件的响应也将变得不可确定。 其次,随着内存不断被分配和释放,整个内存区域会产生越来越多的碎片(因为在使用过程中,申请了一些内存,其中一些释放了,导致
    发表于 04-27 14:26