以下是优化后的内容,结合Markdown与HTML实现可跳转目录:
1. 内存四区
1.1 代码区
📌 核心特性:
- 存储CPU执行的机器指令(二进制代码)
- 共享性:高频程序只需内存保留一份(如标准库函数)
- 只读性:防止意外修改指令(如病毒防护)
⚙️ 操作系统管理:
// 示例:代码区指令不可修改
const char* code_segment = "0x55 0x48 0x89 0xE5"; // 编译后进入代码区
// 尝试修改会触发段错误(Segmentation Fault)
1.2 全局区
📦 存储内容:
数据类型 | 示例 | 生命周期 |
---|---|---|
全局变量 | int global_var = 10; |
程序结束释放 |
静态变量(static修饰) | static int static_var = 20; |
程序结束释放 |
字符串常量 | "Hello, World!" |
程序结束释放 |
const全局常量 | const int MAX_LEN = 100; |
程序结束释放 |
⚠️ 注意:局部常量(如函数内const变量)存放在栈区
1.3 堆区
🛠️ 操作方式:
- C语言:
malloc
分配 /free
释放int* heap_arr = (int*)malloc(10 * sizeof(int)); // 分配堆内存 free(heap_arr); // 必须手动释放,否则内存泄漏
- C++:
new
分配 /delete
释放int* heap_obj = new int(42); // 动态创建对象 delete heap_obj; // 避免悬空指针
🔍 特点:
- 手动管理:程序员需显式控制内存生命周期
- 碎片风险:频繁分配释放可能产生内存碎片
1.4 栈区
⚡ 运行机制:
void example_func() {
int local_var = 30; // 栈区变量
int *alarm = (int *)malloc(sizeof(int)); //指向堆区
static int static_local; // ❌ 静态局部变量在全局区不在栈区!
int* ptr = &local_var; // 指针本身在栈,但指向栈地址
int* ptr1 = alarm; // ❌指针本身在栈,但指向堆地址
} // 函数结束时自动释放local_var和ptr,而ptr1指向的地址在堆区故不对此地址进行回收
🚫 禁止操作:
int* dangerous_return() {
int local_val = 100;
return &local_val; // ❌ 返回栈地址会导致未定义行为
}
2. 程序运行前后内存分布
2.1 运行前的内存分布
🔧 可执行文件结构:
┌───────────────┐
│ 文件头 │ → 包含代码区/全局区长度信息
├───────────────┤
│ 代码区 │ → 机器指令(.text段)
├───────────────┤
│ 全局区 │ → 已初始化数据(.data段)
│ │ 未初始化数据(.bss段)
└───────────────┘
2.2 运行时的内存分布
🏗️ 内存布局:
高地址
┌───────────────┐
│ 栈区 │ ← 向下增长(存储局部变量/参数)
├───────────────┤
│ │
│ 堆区 │ ← 向上增长(动态分配内存)
├───────────────┤
│ .bss段 │ ← 未初始化的全局变量(运行时清零)
├───────────────┤
│ .data段 │ ← 已初始化的全局变量
├───────────────┤
│ 代码区 │ ← 只读指令(加载到Flash)
└───────────────┘
低地址
💡 关键差异:
区域 | 管理方式 | 生命周期 | 典型内容 |
---|---|---|---|
代码区 | 静态预定义 | 程序整个生命周期 | 机器指令 |
全局区 | 静态预定义 | 程序整个生命周期 | 全局变量/静态变量 |
堆区 | 动态分配 | 手动控制 | malloc/new对象 |
栈区 | 编译器自动管理 | 函数作用域 | 局部变量/参数 |