C/C++中的虚拟内存
文章目录
- 一、虚拟内存
- 二、C中的虚拟内存分配模型
- 三、C++中的虚拟内存分配模型
- 四、堆区和栈区的区别
一、虚拟内存
虚拟内存是一种实现在计算机软硬件之间的内存管理技术,它将程序使用到的内存地址(虚拟地址)映射到计算机内存中的物理地址,虚拟内存使得应用程序从繁琐的内存空间管理中解放出来,通过内存隔离提高了内存安全性。
虚拟内存地址通常是连续的地址空间,由操作系统的内存管理模块控制,在触发缺页中断时利用分页技术将实际的物理内存分配给虚拟内存。同时虚拟内存的空间大小远超出实际物理内存的大小,虚拟内存技术使得进程可以使用比物理内存大得多的内存空间。
二、C中的虚拟内存分配模型
C语言中一个进程的内存映像从低地址开始分为正文段、初始化数据段、未初始化数据段、堆区、栈区五大部分:
- Text段:Text段是指用来存放程序执行代码的一块内存区域,是二进制文件(或者说处理器的机器指令)在内存中的映像。当然也有可能包含一些只读的常数变量,例如字符串常量等。这部分区域的大小在程序运行前就已经确定,并且通常只允许进行读操作,向Text段写会导致Segmention Fault。
- Data段:Data段是指存放程序中已经初始化的全局变量和静态变量的一块内存区域。Data段并不是匿名的,而是映射了程序二进制文件中在编译时就已初始化的数据,由程序初始化。
- BSS段:BSS段存放了未初始化的全局变量和静态变量,由操作系统初始化(清零),且是匿名的不映射任何文件,不占用外存空间,只在运行时占用内存。注意,这里的未初始化指的是没有显示初始化,因为全局变量和静态变量会自动隐式初始化为0,但我们没有必要把这些0都存储起来,从而节省外存空间,这也是BSS段的主要作用。
- 堆区:堆提供了程序运行时的内存分配,堆内存的生命周期在函数之外,大部分语言都提供了堆内存管理函数, 如C语言的
malloc()
与free()
,因此堆区由用户管理,可控性强。如果当前堆的内存足够程序使用,则不需要与内核交互,在当前堆中寻找可用内存就行,否则的话需要调用brk()
系统调用向内核申请空间,堆内存分配的算法非常复杂,既要保证内存分配的实时和快速,又要尽量避免堆中出现过多碎片,由此也就引申出了操作系统中的一系列内存分配算法与分配策略,如FF、BF、WF、NF等。 - 栈区:栈保存了局部变量、函数形参、返回值等,调用一个新的函数会在栈上创建一个新的栈帧,当函数返回时这个栈帧会被自动销毁。一个栈帧包括:函数的返回地址和参数、临时变量(包括函数的非静态局部变量以及编译器自动生成的其他临时变量)、栈帧状态值(EBP和ESP,划定了这个函数的栈帧的范围)。栈的空间分配与堆略有不同,当栈空间用尽后继续push会触发栈空间的扩展,导致Page Fault,然后在内核中调用
expand_stack()
,该函数调用acct_stack_growth()
来判断是否可以增长栈空间,如果当前栈空间的大小小于RLIMIT_STACK,则可以继续增长栈空间,该过程由内核完成进程不会感知到。当用户的栈空间已经达到允许的最大值时,内核会给进程发送一个Segmentation Fault信号终止该进程,因此进程的栈空间只会增大不会缩小。
三、C++中的虚拟内存分配模型
C++中的虚拟内存分配与C中大体上相似,只在细节处略有不同:
- 常量区:常量区是一块比较特殊的存储区,专门用来存储那些由const修饰的变量以及常量字符串等不能被修改的常量,在程序结束后由系统释放。
- 全局/静态存储区:存放全局变量和静态变量,程序一经编译该区域就会存在。在C++中,由于编译器会对全局变量和静态变量进行自动初始化并赋值,所以并没有像C中一样对初始化变量和未初始化变量进行区分。全局/静态存储区会在程序结束后由系统释放。
- 自由存储区:自由存储区是通过malloc/calloc/realloc分配的内存,并需要通过free释放。如果程序员没有进行free操作,则会造成内存泄露,并在程序结束时由OS进行内存回收。
- 堆区:与C中不同的是,C++中堆是由new申请的内存,并由delete或delete[]释放。
- 栈区:保存函数中的局部变量、函数参数以及返回值。由编译器负责分配释放,函数结束栈变量也随之失效。
四、堆区和栈区的区别
堆区 | 栈区 | |
---|---|---|
管理者 | 由用户管理,可控性强 | 由系统管理,分配效率高 |
地址扩展 | 从低地址向高地址扩展 | 从高地址向低地址扩展 |
申请后的系统响应 | 如果当前堆的内存足够程序使用,则不需要与内核交互,继续在当前堆中寻找可用内存就行。否则的话需要调用brk() 系统调用向内核申请空间 | 当栈空间用尽后继续请求会触发栈空间的扩展,导致缺页,然后在内核中调用expand_stack() ,该函数调用acct_stack_growth() 来判断是否可以增长栈空间,如果当前栈空间的大小小于RLIMIT_STACK,则可以继续增长栈空间。当用户的栈空间已经达到允许的最大值时,内核会给进程发送一个段错误信号终止该进程。 |
存储内容 | 由用户决定运行时的内存分配 | 栈保存了局部变量、函数形参、返回值等 |
生命周期 | 堆内存的生命周期在函数之外,由用户控制 | 调用一个新的函数会在栈上创建一个新的栈帧,当函数返回时这个栈帧会被自动销毁 |
相关文章:

C/C++中的虚拟内存
文章目录一、虚拟内存二、C中的虚拟内存分配模型三、C中的虚拟内存分配模型四、堆区和栈区的区别一、虚拟内存 虚拟内存是一种实现在计算机软硬件之间的内存管理技术,它将程序使用到的内存地址(虚拟地址)映射到计算机内存中的物理地址&#…...
Qt C++与Python混合编程:补充错误
在提示中,需要引用Python.h,出现错误。 1、找不到Python.h 如果是pro工程,需要在里面配置; INCLUDEPATH /Users/xinnianwang/opt/anaconda3/include LIBS /Users/xinnianwang/opt/anaconda3/lib 如果是CMakeLists.txt需要配…...

2023-04-01:当Go语言遇见FFmpeg视频解码器,使用Go语言改写decode_video.c文件,提升视频解码效率与开发体验。
2023-04-01:当Go语言遇见FFmpeg视频解码器,使用Go语言改写decode_video.c文件,提升视频解码效率与开发体验。 答案2023-04-01: 步骤如下: 1.导入必要的依赖库,包括 fmt、os、unsafe 和其它 FFmpeg 库相关…...

Solidity 学习笔记
主要参考网上资料学习,个人学习笔记有删改,参考出处在文末列出。 0 基础 IDE: remixType Bool: bool public _bool true; 默认false;整型:int、uint、uint256,默认0;地址类型:address,分为 payable 和普…...

ThreadLocal原理
关键点总结: ThreadLocal更像是对其他类型变量的一层包装,通过ThreadLocal的包装使得该变量可以在线程之间隔离和当前线程全局共享。在Thread中有一个threadLocals变量,类型为ThreadLocal.ThreadLocalMap,ThreadLocalMap中key是Th…...
串操作指令详解 MOVS,LODS,STOS,CMPS,SCAS,REP
指令包括:MOVS,LODS,STOS,CMPS,SCAS,REP 串的概念:串是连续存放再内存中的字节块或字块。每个串有一个起始地址和长度, 待操作的数据串称为源串,目的地址称为目标串 目录…...

Java实现判断素数
1 问题 判断101-200之间有多少个素数,并输出所有素数。 2 方法 package homework04; public class Test05 { public static void main(String[] args) { for (int i 101; i < 201; i) { boolean flag true; for (int j 2; j…...

PHP初级教程------------------(2)
目录 运算符 赋值运算符 算术运算符 比较运算符 逻辑运算符 连接运算符 错误抑制符 三目运算符 自操作运算符 编辑 计算机码 位运算符 运算符优先级 流程控制 控制分类 顺序结构 分支结构 If分支 Switch分支 循环结构 For循环 while循环 do-while循环 循环控制 …...
【SQL开发实战技巧】系列(三十五):数仓报表场景☞根据条件返回不同列的数据以及Left /Full Join注意事项
系列文章目录 【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧…...

springBoot自动配置过程介绍
什么是自动配置 以前整合spring mybatis框架时候,需要加很多的bean, 比如说sqlSessionFactory等等 现在springboot帮我们干了,我们只需要引入对应的starter就可以了。 springBoot可以帮我们配置好了一些bean. 如mysql, mogondb相关操作等等ÿ…...

PostgreSQL最后的救命稻草 — pg_resetwal
pg_resetwal— 重置 PostgreSQL 数据库集群的预写日志和其他控制信息 适用版本:PostgreSQL 12/13/14/15语法 pg_resetwal [ -f | --force ] [ -n | --dry-run ] [option...] [ -D | --pgdata ]datadir描述pg_resetwal清除预写日志 WAL,并可选地重置pg_c…...

彻底关闭Windows更新
一、关闭Windows Update服务 1、按“Windows R”键,打开运行对话框,并输入“services.msc”,然后再单击“确定”。 2、在弹出的服务窗口中,找到“Windows Update”选项并双击打开它。 3、在弹出的“Windows Update的属性”对话框…...

Java正则表达式语法
Java正则表达式的语法与示例 | |目录 1匹配验证-验证Email是否正确 2在字符串中查询字符或者字符串 3常用正则表达式 4正则表达式语法 1匹配验证-验证Email是否正确 public static void main(String[] args) { // 要验证的字符串 String str "servicexsoftlab.net&q…...
【2023-3-29】JavaScript使用promise顺序调用函数并抛出异常
JavaScript使用promise顺序调用函数并抛出异常 场景 新建或者编辑时,一个页面中存在多个表单,每个表单都有单独进行表单验证。点击提交时,若有一个表单校验失败,则不能提交。 ps:为啥不放在一个表单中? (…...

Python实现GWO智能灰狼优化算法优化随机森林分类模型(RandomForestClassifier算法)项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 灰狼优化算法(GWO),由澳大利亚格里菲斯大学学者 Mirjalili 等人于2014年提出来的一种群智能…...
从redis到epoll到mmap
redis为什么这么快? 比较容易答出的答案 1)纯粹的内存操作 2)单线程操作,不用考虑线程切换 其他优势 3)I/O 多路复用,使用epoll 4)Reactor 设计模式 I/O 多路复用有三种 select、poll、epoll select:使用数组存储轮询 poll:使用链表轮询 epo…...
STM32CubeMX快速构造工程模板(一)
STM32CubeMX作为一个免费开源的软件,能够可视化配置STM32或其他产品硬件资源,能过快速地构造工程模板,很是方便!!! 目录 STM32CubeMX快速构造工程模板 首先第一步,打开软件-点击按钮-输入型号-双击打开。...

Java Web中的ServletContext对象
目录 ServletContext对象 获取上下文初始化参数的相关方法 创建ServletContext对象 1)通过 GenericServlet 提供的 getServletContext() 方法 2)通过 ServletConfig 提供的 getServletContext() 方法 3)通过 HttpSession 提供的 getServletCo…...

回归预测 | MATLAB实现PSO-RF粒子群算法优化随机森林多输入单输出回归预测
回归预测 | MATLAB实现PSO-RF粒子群算法优化随机森林多输入单输出回归预测 目录回归预测 | MATLAB实现PSO-RF粒子群算法优化随机森林多输入单输出回归预测效果一览基本介绍程序设计参考资料效果一览 基本介绍 MATLAB实现PSO-RF粒子群算法优化随机森林多输入单输出回归预测 粒子…...

在小公司工作3年,从事软件测试5年了,才发现自己还是处于“初级“水平,是不是该放弃....
毕业前三年,从早到晚,加班到深夜,一年又一年,直至刚入职场的首个黄金三年过年都去了,而职位却仍在原地踏步。尽管感觉自己努力过,但是实际上,自身的能力从没得到过多少提升。 所以在无数个夜晚…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...