【C++】内存模型分析
在 C++ 语言中,程序运行时的内存通常被划分为以下几个区域:
- 代码区(Text Segment)
- 常量区(Constant Segment)
- 全局/静态区(Data Segment,包含静态数据段和 BSS 段)
- 堆区(Heap)
- 栈区(Stack)
分布图例如下:

1. 代码区(Text Segment)
- 该区域存放的是程序的机器指令,即代码本身。
- 代码区通常是只读的(read-only),防止程序在运行过程中修改自身代码,提高安全性。
- 在程序启动时由操作系统加载到内存,并且通常所有线程共享这部分内存。
2. 常量区(Constant Segment)
- 该区域用于存储只读的常量,例如字符串字面量和
const关键字修饰的全局常量。 - 常量区通常和代码区一样是只读的,防止意外修改。
- 例如:
const int x = 10; // 存储在常量区
const char* str = "Hello"; // "Hello" 字符串存储在常量区
- 但要注意,
const变量并不一定存储在常量区,例如:
void func() {const int local_const = 5; // 该常量存储在栈区
}
这里 local_const 是局部 const 变量,它仍然存储在栈区,而不是常量区。
3. 全局/静态区(Data Segment)
- 该区域存储全局变量、静态变量(
static修饰的变量)。 - 进一步细分为:
-
- 已初始化数据段(Data Segment):存放已初始化的全局变量和静态变量。
- 未初始化数据段(BSS Segment):存放未初始化的全局变量和静态变量,程序运行时会自动初始化为 0。
示例:
int global_var = 42; // 存在已初始化数据段
static int static_var = 10; // 存在已初始化数据段
int uninitialized_global; // 存在 BSS 段,默认值为 0
static int uninitialized_static; // 存在 BSS 段,默认值为 0
区别:
- 全局/静态变量的生命周期贯穿整个程序运行时间,直到程序退出才被释放。
- 这些变量存储在可读写的内存区域,不同于代码区和常量区的只读特性。
4. 堆区(Heap)
- 堆区用于动态分配的内存,
new或malloc分配的对象存储在这里。 - 由程序员手动管理,如果
new了对象,必须delete,否则会造成内存泄漏。 - 例如:
int* p = new int(5); // 在堆区分配一个 int
delete p; // 释放堆内存
- 注意:
-
- 堆的管理通常由 C++ 运行时库(Runtime Library)和操作系统负责。
- 堆区不像栈区那样自动释放,程序员需要自己管理内存的分配和释放。
5. 栈区(Stack)
- 栈区存储函数调用时的局部变量、函数参数、返回地址等数据。
- 由系统自动管理,函数调用时分配,函数返回时自动释放。
- 栈的分配和回收速度比堆快,因此局部变量的存取效率更高。
- 例如:
void func() {int a = 10; // 局部变量 a 存在栈区
}
- 注意:
-
- 栈的空间有限,过度使用递归或分配过大的局部数组可能导致栈溢出(Stack Overflow)。
常量区 vs. 全局/静态区
两者的主要区别如下:
| 类别 | 存储内容 | 是否可修改 | 存储位置 | 生命周期 |
| 常量区 | 字符串字面量、全局 变量 | 只读 | 代码段的一部分 | 程序运行期间 |
| 全局/静态区 | 全局变量、静态变量 | 可读写 | Data Segment(已初始化/未初始化数据段) | 程序运行期间 |
关键点:
- 常量区是只读的,而全局/静态区是可修改的。
- 字符串字面量存储在常量区,而普通全局/静态变量存储在全局/静态区。
- 局部
const变量存储在栈区,而不是常量区。
全局变量和静态变量的区别
在 C++ 中,全局变量和静态变量的存储位置都属于**“全局/静态存储区”**(Data Segment),但它们之间还是有一些区别的。我们通常把这部分内存区域分成两个概念:
- 全局区(Global Segment)——存储全局变量
- 静态区(Static Segment)——存储静态变量
不过在实际实现上,这两个变量通常都位于全局/静态存储区(Data Segment),只是它们的作用域和访问方式不同。
1. 全局变量(Global Variables)
- 存储位置:存放在全局区(Data Segment 的一部分)。
- 作用域:在整个程序范围内可访问,即在定义它的文件及其他文件中(如果使用
extern声明)。 - 生命周期:从程序启动到程序终止,一直存在,不会被销毁。
- 初始化:
-
- 显式初始化:按照程序员指定的值初始化。
- 默认初始化:如果未初始化,全局变量会被自动初始化为 0(整数)、
nullptr(指针)、0.0(浮点数)。
- 示例:
#include <iostream>int globalVar = 10; // 全局变量,存储在全局区void func() {std::cout << globalVar << std::endl; // 在任何地方都可以访问
}int main() {func(); // 输出 10return 0;
}
- 可被
extern关键字在其他文件中引用:
// file1.cpp
int globalVar = 42;// file2.cpp
extern int globalVar; // 在其他文件中声明
2. 静态变量(Static Variables)
静态变量可以分为静态局部变量和静态全局变量:
(1) 静态全局变量(Static Global Variables)
- 存储位置:存放在静态区(Data Segment 的一部分)。
- 作用域:仅限于定义它的文件内部(文件作用域),不能被其他文件
extern访问。 - 生命周期:从程序启动到程序终止,始终存在。
- 初始化:
-
- 显式初始化:按照程序员指定的值初始化。
- 默认初始化:如果未初始化,静态全局变量会被自动初始化为 0、
nullptr或0.0。
- 示例:
#include <iostream>static int staticGlobalVar = 20; // 静态全局变量void func() {std::cout << staticGlobalVar << std::endl; // 可以访问
}int main() {func(); // 输出 20return 0;
}
- 不能被
extern关键字访问:
// file1.cpp
static int staticVar = 42; // 只能在 file1.cpp 内部访问// file2.cpp
extern int staticVar; // ❌ 错误,无法访问
(2) 静态局部变量(Static Local Variables)
- 存储位置:存放在静态区(Data Segment 的一部分),不会存放在栈上。
- 作用域:仅限于函数内部,但不会在函数调用结束后销毁,下一次调用仍然能访问原来的值。
- 生命周期:在程序运行期间一直存在,直到程序结束。
- 初始化:
-
- 只在函数首次调用时初始化一次,后续调用不会重新初始化。
- 示例:
#include <iostream>void func() {static int counter = 0; // 静态局部变量,初始化仅执行一次counter++;std::cout << "Counter: " << counter << std::endl;
}int main() {func(); // 输出 Counter: 1func(); // 输出 Counter: 2func(); // 输出 Counter: 3return 0;
}
-
counter变量即使func()结束了,也不会被销毁。- 普通局部变量(非 static) 每次调用都会重新初始化,而静态局部变量的值会被保留。
3. 静态区和全局区的区别
(1)存储位置
- 全局变量 存储在全局区(Data Segment 的一部分)。
- 静态变量 存储在静态区(Data Segment 的一部分)。
实际上,全局变量和静态变量都在数据段(Data Segment),但它们的作用域不同,因此有时被称为“全局区”和“静态区”。
(2)作用域
| 变量类型 | 作用域(访问范围) | 可否用 extern 访问 |
| 全局变量 | 整个程序都可以访问 | ✅ 可以使用 |
| 静态全局变量 | 仅限于当前文件(文件作用域) | ❌ 不能跨文件访问 |
| 静态局部变量 | 仅限于当前函数(局部作用域) | ❌ 不能跨函数访问 |
(3)生命周期
| 变量类型 | 生命周期 |
| 全局变量 | 程序运行期间一直存在 |
| 静态全局变量 | 程序运行期间一直存在 |
| 静态局部变量 | 程序运行期间一直存在(不会随着函数结束而销毁) |
| 普通局部变量 | 函数调用时创建,调用结束后销毁 |
(4)初始化
- 全局变量 和 静态变量(全局或局部)如果未手动初始化,会自动初始化为 0 或
nullptr。 - 普通局部变量(非 static) 未初始化时,值是未定义的(随机值)。
4. 总结
- 全局变量存放在全局区(Data Segment),静态变量存放在静态区(Data Segment),但它们都属于“全局/静态存储区”。
- 静态变量包括静态全局变量和静态局部变量:
-
- 静态全局变量 作用域仅限当前文件(不能用
extern)。 - 静态局部变量 作用域仅限当前函数,但生命周期贯穿整个程序运行。
- 静态全局变量 作用域仅限当前文件(不能用
- 静态变量的生命周期比普通局部变量长,即使函数调用结束,静态局部变量的值也不会被销毁,而普通局部变量会被销毁。
- 全局变量可以被
extern访问,静态全局变量不行。 - 静态变量初始化只执行一次,而普通局部变量每次函数调用都会重新初始化。
总结
- C++ 的内存布局分为 代码区、常量区、全局/静态区、堆区和栈区,各有不同的作用和生命周期。
- 常量区与全局/静态区不同,常量区通常是只读的,而全局/静态区可以修改。
- 全局变量和静态变量的生命周期与程序一致,而局部变量在栈上,函数返回时就会被销毁。
- 堆区用于动态分配的内存,需要手动释放,否则可能会发生内存泄漏。
- 栈区用于局部变量和函数调用数据,系统自动分配和回收,但栈的空间有限,可能会发生栈溢出。
相关文章:
【C++】内存模型分析
在 C 语言中,程序运行时的内存通常被划分为以下几个区域: 代码区(Text Segment)常量区(Constant Segment)全局/静态区(Data Segment,包含静态数据段和 BSS 段)堆区&…...
Vue2+OpenLayers携带请求头加载第三方瓦片数据
目录 一、案例截图 二、安装OpenLayers库 三、代码实现 一、案例截图 在对接一些第三方GIS地图的时候,需要携带请求头来验证身份,从而获取相应的瓦片数据,这时候我们需要改造一下WMTS服务的调用方式,效果如图所示: 二、安装OpenLayers库 npm install ol 三、代码实现…...
智能汽车图像及视频处理方案,支持视频实时拍摄特效能力
在智能汽车日新月异的今天,美摄科技作为智能汽车图像及视频处理领域的先行者,凭借其卓越的技术实力和前瞻性的设计理念,为全球智能汽车制造商带来了一场视觉盛宴的革新。美摄科技推出智能汽车图像及视频处理方案,一个集高效性、智…...
Vue 中如何使用 v-model 实现自定义组件的双向绑定?
在 Vue 中,使用 v-model 实现自定义组件的双向绑定需要遵循一套特定的规则。以下是关于如何实现这一功能的详细步骤和示例。 1. 理解 v-model 在 Vue 中,v-model 实际上是语法糖,它在内部实现了 :value 和 @input 的结合。使用 v-model 的自定义组件需要支持以下两个属性:…...
数据结构--顺序表(实现增删改查)
三个文件(Mytest.c 、MySeqList.c 、 MySeqList.h) Mytest.c测试函数 MySeqList.c 函数定义 MySeqList.h函数声明 增删改查的步骤: 初始化 增加元素 • 尾插:先检查顺序表空间是否足够,若不足则进行扩容&#x…...
【android】补充
3.3 常用布局 本节介绍常见的几种布局用法,包括在某个方向上顺序排列的线性布局,参照其他视图的位置相对排列的相对布局,像表格那样分行分列显示的网格布局,以及支持通过滑动操作拉出更多内容的滚动视图。 3.3.1 线性布局Linea…...
HTML 表单处理进阶:验证与提交机制的学习心得与进度(一)
引言 在前端开发的广袤领域中,HTML 表单处理堪称基石般的存在,是构建交互性 Web 应用不可或缺的关键环节。从日常频繁使用的登录注册表单,到功能多样的搜索栏、反馈表单,HTML 表单如同桥梁,紧密连接着用户与 Web 应用…...
23.linux下电脑健康检查
电脑健康检查 硬盘 工具 sudo apt-get install smartmontools检查命令 sudo smartctl -a /dev/sdb1输出结果 # smartctl 7.2 2020-12-30 r5155 [x86_64-linux-6.8.0-52-generic] (local build) # Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools…...
数据库自然连接详解
各类资料学习下载合集 https://pan.quark.cn/s/8c91ccb5a474 数据库自然连接详解 自然连接(Natural Join)是一种在关系型数据库中用于合并两个或多个表的数据的操作。它基于表之间的公共列,自动识别具有相同列名的列,并…...
说说MyBatis一、二级缓存和Spring一二级缓存有什么关系?
大家好,我是锋哥。今天分享关于【说说MyBatis一、二级缓存和Spring一二级缓存有什么关系?】面试题。希望对大家有帮助; 说说MyBatis一、二级缓存和Spring一二级缓存有什么关系? 1000道 互联网大厂Java工程师 精选面试题-Java资源…...
蓝桥杯题型分布2
蓝桥杯 蓝桥杯题型分类2素数孪生素数素数个数朴素筛法求素数线性筛法求素数 因数分解试除法分解质因数 等差素数列梅森素数组素数素数环找素数(分段筛)连续素数和小明的素数对疑似素数质数拆分纯质数超级质数质数日期质数游戏2魔法阵的能量阿坤老师切割年糕阶乘分解…...
北京交通大学第三届C语言积分赛
作者有言在先: 题解的作用是交流思路,不是抄作业的。可以把重点放在思路分析上而不是代码上,毕竟每个人的代码风格是不一样的,看别人的代码就跟做程序填空题一样。先看明白思路再看代码。 还有就是,deepseek真的很好用…...
ESP32学习 -从STM32工程架构进阶到ESP32架构
ESP32与STM32项目文件结构对比解析 以下是对你提供的ESP32项目文件结构的详细解释,并与STM32(以STM32CubeIDE为例)的常见结构进行对比,帮助你理解两者的差异: 1. ESP32项目文件解析 文件/目录作用STM32对应或差异set…...
vue响应式原理剖析
一、什么是响应式? 我们先来看一下响应式意味着什么?我们来看一段代码: m有一个初始化的值,有一段代码使用了这个值; 那么在m有一个新的值时,这段代码可以自动重新执行; let m = 20 console.log(m) console.log(m * 2)m = 40上面的这样一种可以自动响应数据变量的代码机…...
【HTML 基础教程】HTML 元素
HTML 文档由 HTML 元素定义。 HTML 元素 开始标签 *元素内容结束标签 *<p>这是一个段落</p><a href"default.htm">这是一个链接</a><br>换行 *开始标签常被称为起始标签(opening tag),结束标签常称…...
解锁智能制造新体验:兰亭妙微 UE/UI 设计赋能行业变革
在智能制造时代的滚滚浪潮中,企业的数字化转型不仅是技术的革新,更是用户体验与交互界面的全面升级。然而,许多制造企业在这一转型过程中,面临着一系列 UI/UE 设计难题,严重阻碍了企业的数字化发展进程。兰亭妙微凭借专…...
Element UI实现表格全选、半选
制作如图所示的表格全选、半选: 父组件 <template><div id"app"><SelectHost :hostArray"hostArray" /></div> </template><script> import SelectHost from ./components/SelectHost.vue export default…...
如何使用动作捕捉系统训练人形机器人
随着人形机器人变得越来越先进,使用动作捕捉系统教会它们如何像人类一样移动成为了人形机器人领域正在研究的全新方向。本文探讨了如何使用Xsens技术捕捉精确的人类运动数据,使机器人能够通过人工智能和机器学习安全高效地学习、适应和执行复杂任务。 近…...
Vue.js 和 Vue 3 全面详解指南
1. Vue.js 基础介绍 1.1 什么是 Vue.js Vue.js(简称 Vue)是一个用于构建用户界面的渐进式 JavaScript 框架。与其他框架不同,Vue 被设计为可以逐步采用。Vue 的核心库只关注视图层,易于上手,便于与其他库或既有项目整合。 Vue 由尤雨溪(Evan You)在 2014 年创建。尤雨…...
OpenRAND可重复的随机数生成库
OpenRAND 是一个 C++ 库,旨在通过提供强大且可复制的随机数生成解决方案来促进可重复的科学研究。它是一个简单的仅头文件库,性能可移植,统计稳健,并且易于集成到任何 HPC 计算项目中。 特征 跨平台支持:OpenRAND 旨在跨各种平台无缝工作,包括 CPU 和 GPU。其仅标题库设计…...
内网渗透技术 Docker逃逸技术(提权)研究 CSMSF
目录 如何通过上传的webshell判断当前环境是否是物理环境还是Docker环境 方法一:检查文件系统 方法二:查看进程 方法三:检查网络配置 方法四:检查环境变量 方法五:检查挂载点 总结 2. 如果是Docker环境&#x…...
生活电子常识——cmd不能使用anaconda的python环境,导致输入python打开应用商店
前言 电脑已经安装了anaconda,从自带的Anaconda Prompt (Anaconda3)中是可以识别python环境的,然而切换到cmd时,突然发现cmd中无法识别anaconda的python环境,竟然打开了应用商店让我安装Python,这当然是不对的。 解决 这是因为…...
如何在linux中部署dns服务 主备dns (详细全过程)
环境centos 7.9 主DNS:192.168.60.131 备DNS:192.168.60.134 我以 chenxingyu0.com 指向 192.168.60.200为例 首先是主dns #!/bin/bash# 检查是否为 root 用户 if [ "$(id -u)" ! "0" ]; thenecho "请使用…...
Oracle到达梦数据库迁移:技术要点与实践分享
一、达梦数据库简介 达梦数据库(DM,Dameng Database)是国内自主研发的具有自主知识产权的大型通用数据库管理系统,具备以下显著特点: 1.高性能:高效的存储与计算分离架构:达梦数据库采用先进的存储与计算分离架构,能够根据业务需求灵活分配存储和计算资源,大大提高了…...
word写latex-Mathtype安装成功-方法
MathType安装报错 想在word写latexMathtype, 网上搜教程安装, 结果一直报错一直删重来, 一直报错一直删了重来 一直报错一直删了重来来来, 就这么反反复复一直不好 网上的教程都是教你不是删mathtype, 就是删office 时代变了啊&#x…...
【踩坑日记】springboot 打包后实现类无法找到
试过了所有改什么目录 依赖 clean都以失败告终 最后将实现类的文件名从Impl改成impl宣布成功 记得使用idea自带的重构...
deepseek(2)——deepseek 关键技术
1 Multi-Head Latent Attention (MLA) MLA的核心在于通过低秩联合压缩来减少注意力键(keys)和值(values)在推理过程中的缓存,从而提高推理效率: c t K V W D K V h t c_t^{KV} W^{DKV}h_t ctKVWDKVht…...
Linux (Centos7)安装Mongodb4.0.28
一、官网下载安装包上传到服务器系统 官网:https://www.mongodb.com/try/download/community 放在/opt/software目录下: 二、解压至/usr/local目录下,并重新命名为mongodb [rootlocalhost software]# tar -zxvf mongodb-linux-x86_64-rhel7…...
数据库设计-笔记4
1.操作词汇简介 insert:用于向表中插入新记录。 delete:用于从表中删除记录。 update:用于修改表中已有的记录。 select:用于从表中检索数据。 2.代码基础(增删改) -- 修改表中的信息 -- 修改表名 alter table s…...
基于python的图书管理系统设计与实现
摘要 21世纪的今天,随着计算机技术和网络技术的的不断推广发展和应用,图书馆管理方式也应该随之而更新,借由人力进行繁杂重复的图书管理工作已经不再可取,人们对于信息科学化的认识,已由低层次向高层次发展࿰…...
