首页 > 其他分享 >栈区和堆区

栈区和堆区

时间:2024-08-06 18:52:35浏览次数:10  
标签:栈区 泄漏 释放 堆区 内存 空间 这块

        栈区和堆区是两个C++内存管理中的两个区域,而且相当重要,本文详细解释栈和堆之间的概念,内存泄漏和重复释放的原因,以及使用的注意事项。

栈区

        栈区是一块固定大小的空间,从高地址向低地址延申,这块空间由操作系统维护,在使用时,定义的变量依次存入栈中,在变量超出其生命周期后,按照先进后出的顺序进行自动释放,一般来说,我们直接定义的局部变量就是存储在栈区空间的。

        栈空间的示意图可用上图表示,三个变量在定义上的顺序是a、b、c,但是在最后释放时,是按照c、b、a的顺序进行释放的,和数据结构中的栈在存储特点上相同。

栈区注意事项

        因为栈空间有限,所以我们要尤其注意在使用递归函数时,一定要有函数的退出条件,如果无限递归下去,则会导致栈空间存储过多内容而一直释放不掉,从而导致栈溢出,也叫做爆栈,这样会使得程序奔溃,而这样的程序在编译过程中时不会报错的,只有在运行时,系统发现栈溢出,才会终止程序,初学者往往比较难以排查这种错误,所以一般写程序时,如果可以使用循环迭代,就要尽量避免使用函数递归的方式。

堆区

        堆区是一块非常灵活的区域,因为使用这块空间需要程序员自己申请和释放空间,这就使得我们可以根据自己的需求来确定每个空间的使用周期,但是由此引发的问题就是,非常容易导致内存泄漏或者重复释放的问题,这两种问题同样是编译时不会报错。

        内存泄漏:这个问题是我们在使用完堆区空间时,对应的空间没有释放,使得我们在下一次使用堆区空间时,明明这块空间在逻辑上已经没用了可以重新存放其他的数据,但是在物理上,由于我们没有释放这块空间,系统默认这块空间还有用,所以对应的这块内存也不会分配给任何变量,此时如果我们将原指向这块空间的指针置空或者该指针本身已经释放,那么程序员将无法通过任何途径访问到这块空间,使得这块空间在整个程序的运行期间持续占有空间,无法归还系统,这就是内存泄漏。

        说个有趣的事,不知道有没有同学和我一样,初次接触内存泄漏时很紧张,因为我们说内存泄漏会让一块空间永远无法归还内存,所以担心如果程序中频繁且大量出现内存泄漏,会让电脑的内存变得无法使用,甚至需要更换内存条。在这里可以放心的告诉大家,不会的,这里涉及到操作系统给进程分配的虚拟内存,本文不展开讲述,大概意思就是,在程序运行前,操作系统会给这个程序一块空间,在程序运行期间,所有的内存开销都在这块空间进行,在程序结束之后,系统会将这块空间整个释放,也就不会损伤实际的物理内存,但是这不代表我们就可以对内存泄漏放松警惕,如果一个程序需要运行很长的时间,比如说服务器,一个服务器可能要持续运行几个月甚至是几年,如果发生内存泄漏,随着时间的推移,也会使得服务器的效率越来越低。

        重复释放:这个概念就比较好理解了,就是针对同一块堆区空间而言,重复释放了我们申请的这块空间,重复释放会让程序直接终止运行,当我们释放掉一块堆区空间后,后来的变量在申请时就可能会使用到这块空间,如果我们再次进行释放,就会导致后来的变量丢失数据,所以程序会终止。

        

        堆区空间可以这样表示,四个指针对应了我们申请的四块空间,如果此时我们将p2释放,就会得到如下图片:

         我们发现这块空间虽然被释放了,但是p2还指向这块空间,此时如果再对p2解引用,就是访问非法内存,所以我们再释放掉堆区空间之后,对应的指针也应该及时置空。

        相反,如果我们只将指针置空,或者更改指向,就会导致内存泄漏:

         重复释放则是:

        如上图,我们释放p2指向的空间之后,p5申请空间,(图中红色为p5的空间,绿色为p2的空间) 此时如果再次释放p2的空间,会释放p5的空间,导致p5的数据丢失。

堆区注意事项

        综上,我们在使用堆区时,要着重注意两点,即内存泄漏和重复释放问题,好在C++11引入了智能指针,使得我们在堆区的管理上更加方便,智能指针的使用可以参考我的上一篇文章,https://blog.csdn.net/weixin_58234579/article/details/140844702?spm=1001.2014.3001.5501

        合理的使用栈区和堆区可以更方便我们的变量管理和程序的编写,以上就是关于栈区和堆区我所了解的内容,如果有不足和错误之处,请大家指正。

标签:栈区,泄漏,释放,堆区,内存,空间,这块
From: https://blog.csdn.net/weixin_58234579/article/details/140959665

相关文章

  • C++深拷贝构造函数解决浅拷贝的堆区内存重复释放问题
    1.简单介绍先简单介绍一下浅拷贝和深拷贝:浅拷贝->简单的赋值拷贝操作,默认的拷贝构造函数就是浅拷贝。深拷贝->在堆区重新申请空间,进行拷贝操作。2.问题展示下面用代码示例明了地展示默认拷贝构造函数浅拷贝带来地堆区内存重复释放问题:#include<iostream>usingnamespace......
  • 堆空间?栈区?不慌!看完就通透!!
    前言    在进行开发和学习的过程中,我们老是看到或听到“堆空间”,“栈区”,那么他们到底都是什么?有什么关联和区别呢?接下来我们一起看看。什么是堆空间    堆空间是内存管理中的一种区域,用于动态地分配内存给程序中的对象。堆空间允许程序在运行时根据需要分配......
  • 学生管理系统(通过顺序表,获取连续堆区空间实现)
    将学生的信息,以顺序表的方式存储(堆区),并且实现封装函数:1】顺序表的创建,2】判满、3】判空、4】往顺序表里增加学生信息、5】遍历学生信息6】任意位置插入学生信息7】任意位置删除学生信息8】修改学生信息9】查找(按学生的学号查找)、10】删除重复学生信息11】销毁顺序......
  • 深浅拷贝、垃圾回收机制、栈区堆区、文件的操作
    【一】深浅拷贝【1】深浅拷贝问题无论深拷贝还是浅拷贝都是用来复制对象的(1)浅拷贝浅拷贝,只会复制一层,如果copy的对象中有可变数据类型,修改可变数据类型还是会影响拷贝的对象#【1】浅拷贝#必须是修改源数据类型中的可变数据类型才生效#num_list=[1,2,3,4,[1,......
  • 嵌入式中内存分配-栈区、堆区、全局区、常量区和代码区详解
    一、C语言内存分区C语言内存分区示意图如下:1.栈区栈区介绍栈区由编译器自动分配释放,由操作系统自动管理,无须手动管理。栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁。栈区按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自......
  • 栈区、堆区,内存分区模型
    1.栈区由编译器自动分配释放,存放函数的参数值,局部变量等注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放实例代码:#include<iostream>usingnamespacestd;int*func(){inta=10;//局部变量,存放在栈区,栈区的数据在函数执行完后自动释放ret......
  • 动态内存开辟--在堆区进行开辟存储
    1.malloc值//1.malloc--开辟好的空间如果还没有使用,则都默认为随机值#include<stdlib.h>#include<string.h>#include<errno.h>#include<stdio.h>intmain(){ //向堆区内存申请开辟是个整型内存的空间,开辟的空间首地址交给指针p //int*p=(int*)malloc(10*sizeof(int)); ......
  • C语言 堆区空间,malloc
    @TOC前言一、堆区空间的理解:前面测试,普通的数组变量默认最大不能申请1M的空间,甚至远少于1M的空间,毕竟程序中的其他变量也需要使用空间。总共就1M,要省着用。想要使用更大的,没有限制的空间,C语言给我们提供了方式:如下:malloc//申请空间,理论上物理内存有多大,就能申请多大,当然并不能,......
  • 内存存放数据之栈区和堆区
    内存存储数据分为两个区:栈区和堆区栈区存放简单类型的值、复杂类型的内存地址堆区是存放复杂类型的值如果两个变量名同时指向一个复杂类型将如下图所示......
  • 代码区、常量区、静态区(全局区)、堆区、栈区
    代码区、常量区、静态区(全局区)、堆区、栈区?参考:https://blog.csdn.net/u014470361/article/details/79297601......