C/C++ 内存分区详解
一、具体分区
1. 栈区(Stack)
- 存储内容:函数调用时的局部变量、函数参数、返回地址、寄存器值等。
- 特点:由编译器自动管理,后进先出(LIFO),分配速度快,空间连续。
- 示例:
void func() { int a = 10; // 栈上分配 char arr[20]; // 栈上分配 }
2. 堆区(Heap)
- 存储内容:通过
malloc
/calloc
/realloc
(C)或new
(C++)动态分配的内存。 - 特点:手动管理,灵活但易产生碎片,分配速度较慢。
- 示例:
int* ptr = (int*)malloc(sizeof(int)); // C语言 int* cpp_ptr = new int(10); // C++
3. 静态存储区(Static Storage Area)
- 存储内容:
- 全局变量:文件作用域的变量。
- 静态变量:用
static
修饰的变量(全局或局部)。
- 细分区域:
- BSS 段(Block Started by Symbol):未初始化或初始化为 0 的静态变量。
- 数据段(Data Segment):已初始化且初始值非 0 的静态变量。
- 特点:程序启动时分配,程序结束时释放,默认初始化为 0。
- 示例:
int global_uninit; // BSS段(未初始化) static int static_uninit; // BSS段 int global_init = 10; // 数据段(已初始化) static int static_init = 20; // 数据段
4. 代码区(Text Segment)
- 存储内容:程序的可执行代码(机器指令)、常量(如字符串字面量)。
- 特点:通常只读,防止程序意外修改自身指令。
- 示例:
const char* msg = "Hello"; // "Hello" 存储在代码区 // msg 变量本身在栈或静态区
5. 常量区(只读数据段)
- 存储内容:字符串字面量、
const
修饰的全局变量。 - 特点:只读,程序运行期间不可修改。
- 示例:
const int MAX = 100; // 存储在常量区 const char* str = "World"; // "World" 在常量区
6. 内存映射区(Memory Mapping Segment)
- 存储内容:通过
mmap
系统调用映射的文件或共享内存。 - 用途:高效文件操作、进程间通信(IPC)。
- 示例:
// 将文件映射到内存(伪代码) void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
二、C++ 额外的内存区域(相比 C)
1. 自由存储区(Free Store)
- 说明:C++ 中通过
new
和delete
管理的内存区域,概念上类似堆,但实现可能不同(取决于编译器)。 - 区别:
- 堆是操作系统层面的内存管理;自由存储区是 C++ 抽象的概念。
new
底层可能调用malloc
,但可通过重载operator new
自定义实现。
2. 线程局部存储(Thread Local Storage, TLS)
- 存储内容:用
thread_local
修饰的变量,每个线程独立拥有一份副本。 - 示例:
thread_local int counter = 0; // 每个线程有自己的 counter
三、内存分区对比表
区域 | 存储内容 | 生命周期 | 分配方式 | 特点 |
---|---|---|---|---|
栈区 | 局部变量、函数参数、返回地址等 | 函数调用到返回 | 编译器自动管理 | 速度快、连续、容量有限 |
堆区 | 动态分配的内存(malloc /new ) |
手动分配和释放 | 手动管理 | 灵活、碎片、速度慢 |
BSS 段 | 未初始化的静态变量和全局变量 | 程序启动到结束 | 自动初始化 | 初始化为 0 |
数据段 | 已初始化的静态变量和全局变量 | 程序启动到结束 | 自动分配 | 初始化为指定值 |
代码区 | 可执行代码、字符串字面量 | 程序运行期间 | 只读 | 不可修改 |
内存映射区 | 文件映射、共享内存 | 手动映射和解除映射 | 系统调用(如 mmap ) |
高效文件操作 |
四、常见问题
- 内存泄漏:堆内存未释放,导致持续占用。
- 栈溢出:递归过深或局部变量过大,导致栈空间耗尽。
- 野指针:访问已释放的堆内存或未初始化的指针。
理解内存分区有助于编写高效、安全的代码,避免常见的内存错误。
单片机基础知识(C51、STM32)
一、单片机的最小系统
单片机的最小系统是指让单片机能够正常工作所需的 最基本电路单元,不同型号的单片机最小系统略有差异,但核心组成部分基本一致。以经典的 51 系列单片机(如 AT89C51) 为例,其最小系统通常包括以下部分:
1. 单片机芯片(核心)
- 是整个系统的控制中心,负责执行程序、处理数据和控制外设。
- 例如 AT89C51 芯片,内部集成了 CPU、存储器、定时器、串口等模块。
2. 电源电路
- 作用:为单片机提供稳定的工作电压(通常为 5V 或 3.3V,取决于芯片型号)。
- 组成:
- 电源输入端(如 USB 接口、电源适配器)。
- 滤波电容(如 10μF 电解电容 + 0.1μF 瓷片电容),用于稳定电压、滤除高频干扰。
3. 时钟电路(晶振电路)
- 作用:为单片机提供工作时钟信号(主频),控制指令执行的时序。
- 组成:
- 晶振(石英晶体振荡器,常见频率:11.0592MHz、12MHz 等)。
- 起振电容(2 个 10~30pF 瓷片电容,连接晶振两端并接地)。
- 原理:晶振与单片机内部电路构成振荡电路,产生周期性时钟信号。
4. 复位电路
- 作用:使单片机初始化(恢复默认状态),或在程序跑飞时强制重启。
- 组成:
- 上电复位:由电阻和电容组成(如 10kΩ 电阻 + 10μF 电容),上电时电容充电,产生短暂高电平脉冲触发复位。
- 按键复位:在上电复位基础上并联按键,按下按键时直接触发复位。
- 复位信号:通常为高电平有效(不同芯片可能不同)。
5. 程序存储器(可选,取决于单片机类型)
- 对于无片内 ROM 的单片机(如早期的 8031),需外接 EEPROM 或 FLASH 存储器(如 AT28C64)存储程序。
- 现代单片机(如 STC89C52、STM32)通常内置 FLASH,无需外接存储器。
二、单片机的内部主要结构
单片机内部集成了多种功能模块,不同厂商和型号的架构可能不同,但基本结构类似。以下是典型单片机的内部组成:
1. 中央处理器(CPU)
- 核心部件:负责执行指令、处理数据和控制整个系统的运行。
- 组成:
- 算术逻辑单元(ALU):完成算术运算(加、减、乘、除)和逻辑运算(与、或、非、异或等)。
- 控制器:产生时序信号,控制指令的读取、解码和执行。
- 寄存器组:包括累加器(ACC)、程序状态字寄存器(PSW)、数据指针(DPTR)等,用于暂存数据和中间结果。
2. 存储器系统
单片机的存储器通常采用 哈佛结构(程序存储器和数据存储器分开)或 冯诺依曼结构(统一编址)。
- 程序存储器(ROM/FLASH):
- 用于存储用户编写的程序代码和常数(如查表数据)。
- 掉电后数据不丢失(非易失性)。
- 数据存储器(RAM):
- 用于存储运行时的临时数据(如变量、堆栈)。
- 掉电后数据丢失(易失性)。
3. 寄存器组
- 是 CPU 内部的高速存储单元,用于快速访问数据,包括:
- 通用寄存器:如 51 单片机的 R0~R7,用于暂存运算数据。
- 特殊功能寄存器(SFR):用于控制单片机的外设模块(如定时器、串口、中断等),例如:
- 定时器控制寄存器(TMOD、TCON)。
- 串口控制寄存器(SCON)。
- 中断允许寄存器(IE)。
4. 外设模块
单片机内部集成了丰富的外设,用于实现不同功能:
- 定时器 / 计数器:用于产生定时信号或计数外部事件(如 51 单片机的 T0、T1)。
- 串行通信接口(UART/USART):用于单片机与其他设备(如 PC、传感器)的异步通信。
- 并行 I/O 口:如 51 单片机的 P0~P3 口,可配置为输入或输出模式,连接外部设备(如 LED、按键、LCD)。
- 模拟信号处理模块:
- 模数转换器(ADC):将模拟信号转换为数字信号(如 STM32 的 ADC 模块)。
- 数模转换器(DAC):将数字信号转换为模拟信号(部分高端单片机具备)。
- 中断系统:用于处理外部事件(如按键触发、定时器溢出),提高 CPU 效率。
- 其他模块:SPI、I²C 通信接口,看门狗定时器(WDT),PWM 输出等。
5. 系统总线
- 是单片机内部各模块之间传输数据、地址和控制信号的通道,包括:
- 地址总线(AB):传输存储器或外设的地址信号。
- 数据总线(DB):传输数据信号。
- 控制总线(CB):传输控制信号(如读 / 写命令、中断请求等)。
三、典型单片机对比(以 51 和 STM32 为例)
特性 | 51 系列(如 AT89C51) | STM32(ARM Cortex-M 系列) |
---|---|---|
架构 | 哈佛结构,8 位 CPU | 哈佛结构,32 位 ARM Cortex-M 内核 |
存储器 | 片内 FLASH(4~64KB),RAM(128~256B) | 片内 FLASH(几十 KB~ 几 MB),RAM(几十 KB) |
外设 | 基本定时器、UART、并行 I/O | 丰富外设(ADC、DAC、USB、CAN、SDIO 等) |
主频 | 最高约 24MHz | 最高可达 200MHz 以上 |
应用场景 | 简单控制、低成本场景(如家电、玩具) | 中高端嵌入式系统(如工业控制、物联网) |
四、总结
- 最小系统:是单片机运行的基础,核心包括电源、晶振、复位电路和芯片本身。
- 内部结构:以 CPU 为核心,搭配存储器、寄存器和各类外设模块,通过总线协同工作。
- 学习建议:初学者可从 51 单片机入手,理解最小系统搭建和寄存器操作,再进阶到 32 位单片机(如 STM32),学习 HAL 库或寄存器编程。