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

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

一、内存

在计算机中,每个应用程序之间的内存是相互独立的,通常情况下应用程序 A 并不能访问应用程序 B,当然一些特殊技巧可以访问,但此文并不详细进行说明。例如在计算机中,一个视频播放程序与一个浏览器程序,它们的内存并不能访问,每个程序所拥有的内存是分区进行管理的。

在计算机系统中,运行程序 A 将会在内存中开辟程序 A 的内存区域 1,运行程序 B 将会在内存中开辟程序 B 的内存区域 2,内存区域 1 与内存区域 2 之间逻辑分隔。

1.1 内存四区

在程序 A 开辟的内存区域 1 会被分为几个区域,这就是内存四区,内存四区分为栈区、堆区、数据区与代码区。

栈区指的是存储一些临时变量的区域,临时变量包括了局部变量、返回值、参数、返回地址等,当这些变量超出了当前作用域时将会自动弹出。该栈的最大存储是有大小的,该值固定,超过该大小将会造成栈溢出。

堆区指的是一个比较大的内存空间,主要用于对动态内存的分配;在程序开发中一般是开发人员进行分配与释放,若在程序结束时都未释放,系统将会自动进行回收。

数据区指的是主要存放全局变量、常量和静态变量的区域,数据区又可以进行划分,分为全局区与静态区。全局变量与静态变量将会存放至该区域。

代码区就比较好理解了,主要是存储可执行代码,该区域的属性是只读的。

1.2 使用代码证实内存四区的底层结构

由于栈区与堆区的底层结构比较直观的表现,在此使用代码只演示这两个概念。首先查看代码观察栈区的内存地址分配情况:

1

2

3

4

5

6

7

8

#include<stdio.h>

intmain()

{

inta = 0;

intb = 0;

charc='0';

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 三个变量同属于一个栈内,所以它们地址的索引是连续性的,那如果我创建一个静态变量将会如何?在以上内容中说明了静态变量存储在静态区内,我们现在就来证实一下:

1

2

3

4

5

6

7

8

9

10

#include<stdio.h>

intmain()

{

inta = 0;

intb = 0;

charc='0';

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 的地址并不存在连续,他们两个的内存地址是分开的。那接下来在此建一个全局变量,通过上述内容得知,全局变量与静态变量都应该存储在静态区,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

#include<stdio.h>

inte = 0;

intmain()

{

inta = 0;

intb = 0;

charc='0';

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);

}

运行结果如下:

从以上运行结果中证实了上述内容的真实性,并且也得到了一个知识点,栈区、数据区都是使用栈结构对数据进行存储。

在以上内容中还说明了一点栈的特性,就是容量具有固定大小,超过最大容量将会造成栈溢出。查看如下代码:

1

2

3

4

5

6

#include<stdio.h>

intmain()

{

chararr_char[1024*1000000];

arr_char[0] ='0';

}

以上代码定义了一个字符数组 arr_char,并且设置了大小为 1024*1000000,设置该数据是方便查看大小;随后在数组头部进行赋值。运行结果如下:

这是程序运行出错,原因是造成了栈的溢出。在平常开发中若需要大容量的内存,需要使用堆。

堆并没有栈一样的结构,也没有栈一样的先进后出。需要人为的对内存进行分配使用。代码如下:

1

2

3

4

5

6

7

8

9

#include<stdio.h>

#include<string.h>

#include <malloc.h>

intmain()

{

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 的使用

在开辟堆空间时我们使用的函数为 malloc,malloc 在 C 语言中是用于申请内存空间,malloc 函数的原型如下:

1

void*malloc(size_tsize);

在 malloc 函数中,size 是表示需要申请的内存空间大小,申请成功将会返回该内存空间的地址;申请失败则会返回 NULL,并且申请成功也不会自动进行初始化。细心的同学可能会发现,该函数的返回值说明为 void *,在这里 void * 并不指代某一种特定的类型,而是说明该类型不确定,通过接收的指针变量从而进行类型的转换。在分配内存时需要注意,即时在程序关闭时系统会自动回收该手动申请的内存 ,但也要进行手动的释放,保证内存能够在不需要时返回至堆空间,使内存能够合理的分配使用。

http://www.jsqmd.com/news/895249/

相关文章:

  • 告别卡顿!在CIM/UE5大场景中,这几种LOD切换策略到底该怎么选?
  • FPGA图像缩放项目避坑指南:从HLS到纯Verilog,如何选择与移植(以Kintex7为例)
  • 别再只用labelme了!用ENVI 5.3的ROI工具给遥感影像打深度学习标签(附Python转换脚本)
  • 从自建OAuth令牌管理到Auth0 Token Vault:AI应用安全架构演进实践
  • 别只调代码了!STM32F4 USB3300虚拟串口不通?硬件焊接与信号完整性自查清单
  • 基于LLM与向量数据库的代码库智能问答系统构建指南
  • Unity游戏逆向实战:用dnSpy调试修改《XX游戏》的伤害数值(附mono.dll替换避坑指南)
  • AI时代人机协同:从工具依赖到价值重构的实践思考
  • MCB1700评估板连接器布局与设计要点详解
  • AI如何成为你的演讲设计师:从婚礼致辞到悼词写作的实践指南
  • 什么是列表
  • 深入浅出:IPMSM无感FOC中,为什么方波注入比正弦波注入更‘抗造’?
  • 陕西沫清风户外用品与西安永辉户外遮阳用品有限公司关系深度解析
  • 2026年论文AI疑似度高达90%?这几招物理降AI法搭工具,快速降AI率到10%! - 降AI实验室
  • OpenAI Realtime API 实战:WebSocket流式语音对话开发指南
  • XUnity.AutoTranslator:5分钟上手,让你无障碍畅玩全球Unity游戏
  • 从Maya到Unity:手把手教你用BlendShape制作会‘说话’的3D角色面部
  • 手把手教你用VMware Workstation Pro免费搭建FortiWeb 6.3.4虚拟机(附下载与网络配置避坑指南)
  • 虚幻引擎粒子系统二选一?从Cascade到Niagara,给美术和技术策划的迁移实战指南
  • 从robots.txt到agents.txt:IETF草案过期的启示与机器人协议演进
  • AI编码助手安全实践:基于沙箱与可复现环境的隔离方案
  • AI 技术日报 - 2026-05-27
  • 思维导图笔记:RAG检索增强生成
  • 零成本AI网站审计:用Claude免费进行预发布质量检查
  • Express CORS安全配置:从AI生成代码陷阱到生产级最佳实践
  • MCP协议:打通AI与渗透测试工具的语义鸿沟
  • GPU加速分布式深度学习中的计算通信重叠技术解析
  • 【上海市浦东新区计算机协会主办,阳光学院支持 | ACM ICPS 出版 ,ISBN号:979-8-4007-2532-6】第三届人工智能与自然语言处理国际学术会议(AINLP 2026)
  • LLM智能体架构与工程实践:从核心概念到生产部署指南
  • SIM800C模块搭配STM32F407实战:从硬件接线到打通第一个电话的避坑全记录