当前位置: 首页 > news >正文

C语言与C++内存管理超详细分析

一、内存在计算机中每个应用程序之间的内存是相互独立的通常情况下应用程序 A 并不能访问应用程序 B当然一些特殊技巧可以访问但此文并不详细进行说明。例如在计算机中一个视频播放程序与一个浏览器程序它们的内存并不能访问每个程序所拥有的内存是分区进行管理的。在计算机系统中运行程序 A 将会在内存中开辟程序 A 的内存区域 1运行程序 B 将会在内存中开辟程序 B 的内存区域 2内存区域 1 与内存区域 2 之间逻辑分隔。1.1 内存四区在程序 A 开辟的内存区域 1 会被分为几个区域这就是内存四区内存四区分为栈区、堆区、数据区与代码区。栈区指的是存储一些临时变量的区域临时变量包括了局部变量、返回值、参数、返回地址等当这些变量超出了当前作用域时将会自动弹出。该栈的最大存储是有大小的该值固定超过该大小将会造成栈溢出。堆区指的是一个比较大的内存空间主要用于对动态内存的分配在程序开发中一般是开发人员进行分配与释放若在程序结束时都未释放系统将会自动进行回收。数据区指的是主要存放全局变量、常量和静态变量的区域数据区又可以进行划分分为全局区与静态区。全局变量与静态变量将会存放至该区域。代码区就比较好理解了主要是存储可执行代码该区域的属性是只读的。1.2 使用代码证实内存四区的底层结构由于栈区与堆区的底层结构比较直观的表现在此使用代码只演示这两个概念。首先查看代码观察栈区的内存地址分配情况12345678#includestdio.hintmain(){inta 0;intb 0;charc0;printf(变量a的地址是%d\n变量b的地址是%d\n变量c的地址是%d\n, a, b, c);}运行结果为我们可以观察到变量 a 的地址是 2293324 变量 b 的地址是 2293320由于 int 的数据大小为 4 所以两者之间间隔为 4再查看变量 c我们发现变量 c 的地址为 2293319与变量 b 的地址 2293324 间隔 1因为 c 的数据类型为 char类型大小为 1。在此我们观察发现明明我创建变量的时候顺序是 a 到 b 再到 c为什么它们之间的地址不是增加而是减少呢那是因为栈区的一种数据存储结构为先进后出如图首先栈的顶部为地址的“最小”索引随后往下依次增大但是由于堆栈的特殊存储结构我们将变量 a 先进行存储那么它的一个索引地址将会是最大的随后依次减少第二次存储的值是 b该值的地址索引比 a 小由于 int 的数据大小为 4所以在 a 地址为 2293324 的基础上往上减少 4 为 2293320在存储 c 的时候为 char大小为 1则地址为 2293319。由于 a、b、c 三个变量同属于一个栈内所以它们地址的索引是连续性的那如果我创建一个静态变量将会如何在以上内容中说明了静态变量存储在静态区内我们现在就来证实一下12345678910#includestdio.hintmain(){inta 0;intb 0;charc0;staticintd 0;printf(变量a的地址是%d\n变量b的地址是%d\n变量c的地址是%d\n, a, b, c);printf(静态变量d的地址是%d\n, d);}运行结果如下以上代码中创建了一个变量 d变量 d 为静态变量运行代码后从结果上得知静态变量 d 的地址与一般变量 a、b、c 的地址并不存在连续他们两个的内存地址是分开的。那接下来在此建一个全局变量通过上述内容得知全局变量与静态变量都应该存储在静态区代码如下123456789101112#includestdio.hinte 0;intmain(){inta 0;intb 0;charc0;staticintd 0;printf(变量a的地址是%d\n变量b的地址是%d\n变量c的地址是%d\n, a, b, c);printf(静态变量d的地址是%d\n, d);printf(全局变量e的地址是%d\n, e);}运行结果如下从以上运行结果中证实了上述内容的真实性并且也得到了一个知识点栈区、数据区都是使用栈结构对数据进行存储。在以上内容中还说明了一点栈的特性就是容量具有固定大小超过最大容量将会造成栈溢出。查看如下代码123456#includestdio.hintmain(){chararr_char[1024*1000000];arr_char[0] 0;}以上代码定义了一个字符数组 arr_char并且设置了大小为 1024*1000000设置该数据是方便查看大小随后在数组头部进行赋值。运行结果如下这是程序运行出错原因是造成了栈的溢出。在平常开发中若需要大容量的内存需要使用堆。堆并没有栈一样的结构也没有栈一样的先进后出。需要人为的对内存进行分配使用。代码如下123456789#includestdio.h#includestring.h#include malloc.hintmain(){char*p1 (char*)malloc(1024*1000000);strcpy(p1,这里是堆区);printf(%s\n, p1);}以上代码中使用了strcpy 往手动开辟的内存空间 p1 中传数据“这里是堆区”手动开辟空间使用 malloc传入申请开辟的空间大小 1024*1000000在栈中那么大的空间必定会造成栈溢出而堆本身就是大容量则不会出现该情况。随后输出开辟的内存中内容运行结果如下在此要注意p1是表示开辟的内存空间地址。二、malloc 和 free在 C 语言不是 C)中malloc 和 free 是系统提供的函数成对使用用于从堆中分配和释放内存。malloc 的全称是 memory allocation 译为“动态内存分配”。2.1 malloc 和 free 的使用在开辟堆空间时我们使用的函数为 mallocmalloc 在 C 语言中是用于申请内存空间malloc 函数的原型如下1void*malloc(size_tsize);在 malloc 函数中size 是表示需要申请的内存空间大小申请成功将会返回该内存空间的地址申请失败则会返回 NULL并且申请成功也不会自动进行初始化。细心的同学可能会发现该函数的返回值说明为 void *在这里 void * 并不指代某一种特定的类型而是说明该类型不确定通过接收的指针变量从而进行类型的转换。在分配内存时需要注意即时在程序关闭时系统会自动回收该手动申请的内存 但也要进行手动的释放保证内存能够在不需要时返回至堆空间使内存能够合理的分配使用。
http://www.gsyq.cn/news/1400123.html

相关文章:

  • 陕西沫清风户外用品与西安永辉户外遮阳用品有限公司关系深度解析
  • 2026年论文AI疑似度高达90%?这几招物理降AI法搭工具,快速降AI率到10%! - 降AI实验室
  • Scrcpy连接阶段避坑指南:SDL事件循环与adb端口映射的常见问题排查
  • C++ primer超详细讲解泛型算法
  • 树莓派远程桌面不止xrdp:试试更流畅的VNC Viewer配置与优化技巧
  • AI编码助手安全实践:基于沙箱与可复现环境的隔离方案
  • GPU加速分布式深度学习中的计算通信重叠技术解析
  • 思维导图笔记:RAG检索增强生成
  • MCP协议:打通AI与渗透测试工具的语义鸿沟
  • EhViewer开源漫画阅读器:从零开始的5个必知功能与完整使用手册
  • Glasswing:从被动响应到主动免疫的运行时安全架构实战
  • 从RSSI到AoA:手把手教你用ESP32和Arduino搭建一个简易的无线定位实验系统
  • AI编码时代:当开发效率飙升,如何守住软件质量底线?
  • 从Anthropic代码泄露事件看软件供应链安全与AI服务架构
  • ACS Z轴回零程序 项目实战
  • Android混合加固逆向实战:VMP虚拟化与Dex2C内存Dump全链路突破
  • 告别驱动烦恼:在Vue项目中用BrowserPrint API直连斑马打印机(ZD420/ZTC系列)
  • Unity 2D Tilemap保姆级避坑指南:从素材切割到碰撞体合并,搞定你的复古风游戏地图
  • Tomcat CVE-2024-50379与CVE-2024-52318深度解析与四层加固
  • 表单自动提交:自动填写并提交问卷调查,获取结果页数据,爬虫实战:利用Python实现问卷调查自动填写与结果数据采集
  • 优化UE4项目内存:深入理解Texture Streaming机制与STAT STREAMING命令实战分析
  • Codex App 64K最优开发配置|舍弃1M冗余上下文,大幅降低无效Token消耗
  • 基于YOLO26的草莓果实病害识别检测系统研究(项目源码+数据集+模型权重+UI界面+python+深度学习+远程环境部署)
  • H2O AutoML工业级机器学习流水线实战指南
  • 手把手教你用Windows Server 2019搭建Exchange 2016 CU23邮件服务器(附下载链接与避坑指南)
  • 别再死记硬背了!用Wirtinger导数搞定复数求导,附Python代码验证
  • 别再到处找了!银河麒麟V10服务器版/桌面版最新下载链接与安装镜像校验全攻略
  • 开发岗的AI协作能力要求
  • 零成本AI网站审计:用Claude免费进行预发布质量检查
  • 别再乱用Update了!Unity里FixedUpdate、Update、LateUpdate的实战避坑指南(附Time.deltaTime详解)