C++内存模型

目录

内存模型分类

堆和栈的区别

C++中new的工作过程

堆和栈的区别

为什么堆区要比栈区大


内存模型分类

  • 文本段(ELF)(数据区):主要用于存放我们编写的代码,但是不是按照代码文本的形式存放,而是将代码文本编译成二进制代码,存放的是二进制代码,在编译时就已经确定这个区域存放的内容是什么了,并且这个区域是只读区域;
  • DATA段(初始化静态区,常量区):这个区域主要用于存放编译阶段(非运行阶段时)就能确定的数据,也就是初始化的静态变量、全局变量和常量,这个区域是可读可写的。这也就是我们通常说的静态存储区;
  • BSS段(静态区):这个区域存放的是未曾初始化的静态变量、全局变量,但是不会存放常量,因为常量在定义的时候就一定会赋值了。未初始化的全局变量和静态变量,编译器在编译阶段都会将其默认为0;
  • HEAP(堆):这个区域实在运行时使用的,主要是用来存放程序员分配和释放内存,程序结束时操作系统会对其进行回收,(程序员分配内存像malloc、free、new、delete)都是在这个区域进行的;
  • STACK(栈):存放函数的参数值和局部变量,这个区域的数据是由编译器来自己分配和释放的,只要执行完这个函数,那么这些参数值和变量都会被释放掉;
  • 内核空间(env)环境变量:这个区域是系统内部的区域,我们是不可编辑的;

堆和栈的区别

C++中new的工作过程

申请的是普通的内置类型的空间:

(1)调用 C++标准库中 operator new函数,传入大小。(如果申请的是0byte则强制转化成1byte)

(2)申请相对应的空间,如果没有足够的空间或其他问题且没有定义_new_hanlder,那么会抛出bad_alloc的异常并结束程序,如果定义了_new_hanlder回调函数,那么会一直不停的调用这个函数直到问题被解决为止

(3)返回申请到的内存的首地址.

申请的是类空间:

(1)如果是申请的是0byte,强制转换为1byte

(2)申请相对应的空间,如果没有足够的空间或其他问题且没有定义_new_hanlder,那么会抛出bad_alloc的异常并结束程序

(3)如果定义了_new_hanlder回调函数,那么会一直不停的调用这个函数直到问题被解决为止。

(4)如果这个类没有定义任何构造函数,析构函数,且编译器没有合成,那么下面的步骤跟申请普通的内置类型是一样的。

(5)如果有构造函数或者析构函数,那么会调用一个库函数,具体什么库函数依编译器不同而不同,这个库函数会回调类的构造函数。

(6)如果在构造函数中发生异常,那么会释放刚刚申请的空间并返回异常

(7)返回申请到的内存的首地址

delete 与new相反,会先调用析构函数再去释放内存(delete 实际调用 operator delete)

operator new[]的形参是 sizeof(T)*N+4就是总大小加上一个4(用来保存个数);空间中前四个字节保存填充长度。然后执行N次operator new

operator delete[] 类似;

堆和栈的区别

全局数据区存放静态数据、全局变量、常量。

代码区存放所有类成员函数和非成员函数的代码。

栈区存放用于函数的返回地址、形参、局部变量、返回类型。

堆区存放余下的内存(new和delete)。

  1. 申请方式不同:栈是系统自动分配,堆是程序员申请。
  2. 系统响应不同:
  • 栈:只要栈的剩余空间大于所申请的空间,系统就会为程序提供内存,否则栈溢出。
  • 堆:系统收到申请空间的请求后,会遍历一个操作系统用于记录内存空闲地址的链表,当找到一个空间大于所申请空间的堆结点后,就会为该结点从记录内存空闲地址的链表中删除,并将该结点的内存分配给程序,然后在这块内存区域的首地址处记录分配的大小,这样我们在使用delete来释放内存的时候,delete才能正确地识别并删除该内存区域的所有变量。另外,我们申请的内存空间与堆结点的内存空间不一定相等,这是系统会自动将堆结点上多出来的那部分内存空间回收到空闲链表中。空间大小不同:栈是一块连续的区域,大小一般是1~2M;堆是不连续的区域,空间很大,上限取决于有效的虚拟内存。
  1. 碎片问题:栈是后进先出的队列,内存是连续的,而堆则在多次的new和delete后会产生很多碎片。
  2. 生长方向:栈是向下,堆是向上。
  3. 分配方式:堆是动态分配,没有静态分配。栈是静态分配和动态分配,静态分配由编译器完成,例如局部变量的内存分配;动态分配则由alloca函数分配,不同于堆的手工释放,它的分配是完全由编译器自动释放。
  4. 分配效率:栈是系统的底层数据结构,由专门的寄存器存放栈的地址,专门指令执行压栈出栈,这就决定了栈的效率比较高。而堆是C++函数库提供的,机制复杂,效率低。

为什么堆区要比栈区大

堆干很多事情例如在new一个对象的时候就在堆内存中分配的,那么堆内存是如何管理的呢?堆内存空余内存地址是一个链表的结构存储的,当一个程序请求过来的时候(此时所需的内存大小已经计算好),就会开始遍历这个链表找个比这个程序所需内存大的节点用来给你程序执行所用,此时就会在链表的节点上删除这个即将被占用的内存节点,因为new对象的这个过程是比较缓慢的而且链表上的每个节点内存大小也是不确定的所以就会产生内存碎片,不过用起来非常方便。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/105667.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux学习记录——이십오 多线程(2)

文章目录 1、理解原生线程库线程局部存储 2、互斥1、并发代码(抢票)2、锁3、互斥锁的实现原理 3、线程封装1、线程本体2、封装锁 4、线程安全5、死锁6、线程同步1、条件变量1、接口2、demo代码 1、理解原生线程库 线程库在物理内存中存在,也…

Web服务器端应用开发

一、登录验证器 1.1相关概念 登录验证器是一种用于提高帐户安全性的应用或设备,它可以在你输入用户名和密码后,生成或接收一个一次性的验证码或通知,以进行第二次身份验证。这样,即使你的密码被泄露或破解,其他人也无…

如何使用海艺人工智能生成创意汉字

1、用某种字体生成文字。 jf storehttps://store.justfont.com/fonts 2、打开seaart。ai网站。https://www.seaart.ai/home 3、效果如下。 4、右键保存图片。

浏览器跨域

生活中的事跟跨域有什么关系,那必须有。 跨域的产生是浏览器的安全机制引起的,只有在使用Ajax时才会发生。简单来说就是你可以通过ajax发送请求,但要看远程服务器脸色,他没授权,浏览器这个老六就给拦截了,不…

【实操干货】如何开始用Qt Widgets编程?(三)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 在本文中&#xff0…

数据结构入门 — 链表详解_双向链表

前言 数据结构入门 — 双向链表详解* 博客主页链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 文章末尾有源码 *****感谢观看,希望对你有所帮助***** 系列文章 第一篇:数据结构入门 — 链表详解_单链表…

Windows 转 mac 记录

初次从Windows转mac可能会不适应,建议先看看 【6分钟搞定MacBook】不懂时无所适从,学会后越用越爽!_哔哩哔哩_bilibili 我主要是做一些补充记录 1、Windows的右键等于mac的双击触控板、control单击触控板 2、运行中的应用下方会有一个点&…

深度学习:Sigmoid函数与Sigmoid层区别

深度学习:Sigmoid函数与Sigmoid层 1. Sigmoid神经网络层 vs. Sigmoid激活函数 在深度学习和神经网络中,“Sigmoid” 是一个常见的术语,通常用来表示两个相关但不同的概念:Sigmoid激活函数和Sigmoid神经网络层。这两者在神经网络…

go语言学习之有关变量的知识

文章目录 变量的学习1.变量的使用步骤2.变量的注意事项3.变量使用的三种方式:4.程序中 号的使用5.变量的数据类型1)int数据类型2)小数类型浮点型3)**字符类型**4)**字符串(String)类型**5&…

激活函数总结(十七):激活函数补充(PELU、Phish)

激活函数总结(十七):激活函数补充 1 引言2 激活函数2.1 Parametric Exponential Linear Unit(PELU)激活函数2.2 Phish激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、…

Spring Boot中使用validator如何实现接口入参自动检验

文章目录 一、背景二、使用三、举例 一、背景 在项目开发过程中,经常会对一些字段进行校验,比如字段的非空校验、字段的长度校验等,如果在每个需要的地方写一堆if else 会让你的代码变的冗余笨重且相对不好维护,如何更加规范和优…

网关认证的技术方案

我们认证授权使用springsecurity 和oauth2技术尽心实现具体实现流程见第五章文档,这里就是记录一下我们的技术方案 这是最开始的技术方案,我们通过认证为服务获取令牌然后使用令牌访问微服务,微服务解析令牌即可。但是缺点就是每个微服务都要…

听GPT 讲Prometheus源代码--util

Prometheus的util目录包含了一些通用的工具模块,主要包含以下文件: buckets.go 这个文件定义了一些常用的指标采样值范围(Quantile buckets),如:0.001,0.01,0.05,0.5,0.9,0.95,0.99,0.999等。这些buckets常用于计算指标的分位数线。 regex.go 这个文件定义了一些正则表达式匹配…

【在Windows下搭建Tomcat HTTP服务】

文章目录 前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册 2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置 3.公网访问测试4.结语 前言 Tomcat作为一个轻量级的服务器,不仅名字很有趣&#xff0…

【ArcGIS微课1000例】0071:普通最小二乘法 (OLS)回归分析案例

严重声明:本文来自专栏《ArcGIS微课1000例:从点滴到精通》,为CSDN博客专家刘一哥GIS原创,原文及专栏地址为:(https://blog.csdn.net/lucky51222/category_11121281.html),谢绝转载或爬取!!! 文章目录 一、空间自回归模型二、ArcGIS普通最小二乘法回归(OLS)一、空间自…

VMware虚拟机连不上网络

固定ip地址 进入网络配置文件 cd /etc/sysconfig/network-scripts 打开文件 vi ifcfg-ens33 编辑 BOOTPROTO设置为static,有3个值(decp、none、static) BOOTPROTO"static" 打开网络 ONBOOT"yes" 固定ip IPADDR1…

AI智能语音机器人的基本业务流程

先画个图,了解下AI语音机器人的基本业务流程。 上图是一个AI语音机器人的业务流程,简单来说就是首先要配置话术,就是告诉机器人在遇到问题该怎么回答,这个不同公司不同行业的差别比较大,所以一般每个客户都会配置其个性…

Android项目如何上传Gitee仓库

前言 最近Android项目比较多,我都是把Android项目上传到Gitee中去,GitHub的话我用的少,可能我还是更喜欢Gitee吧,毕竟Gitee仓库用起来更加方便 一. 创建Gitee仓库 1. 先创建一个Gitee账号,然后登录上去 2. 创建Androi…

板卡设计+硬件每日学习十个知识点(44)23.8.24 (检测单元设计,接口部分设计,板卡电源输入设计,电源检测电路)

文章目录 1.检测单元介绍(使用GD32单片机)2.GD32的最小系统板3.GD32的温度监测4.GD32的电压监测和电流监测5.GD32的布线6.接口部分设计7.板卡电源输入设计8.电源检测电路 1.检测单元介绍(使用GD32单片机) 答: 首先要为…

融合算法综述

融合算法 前言一、概念二、原理三、融合的先决条件四、融合分类4.1、前融合和后融合4.2 、数据级融合、特征级融合和决策级融合 五、典型融合算法 多传感器信息融合(Multi-sensor Information Fusion,MSIF):利用计算机技术将来自多传感器或多…