程序内存分区思维导图
程序内存分区知识图谱
程序内存分区详解
深入理解计算机程序的内存布局与管理机制
程序内存分区详解
1. 指令存放区 (.text段)
- 存储内容:可执行机器指令
- 权限:只读 + 可执行
- 管理:编译器生成,操作系统加载
- 生命周期:程序运行期
2. 数据存放区
A. 栈区 (Stack)
- 核心标志:局部变量、函数参数
- 访问方式:CPU直接通过栈指针访问
- 生长方向:高地址→低地址
- 管理:编译器自动分配/释放
- 生命周期:函数调用期间
- 大小限制:通常8MB(可调)
- 存储内容:
- 函数参数
- 局部变量
- 返回地址
- 局部const变量(非全局)
- 函数调用上下文
B. 堆区 (Heap)
- 核心标志:动态分配内存
- 访问方式:通过指针间接访问
- 生长方向:低地址→高地址
- 管理:程序员手动管理
- 分配:malloc/calloc/realloc, new
- 释放:free, delete
- 生命周期:程序员控制
- 大小限制:系统虚拟内存限制
- 存储内容:
- 动态数组
- 动态对象
- 任意大小数据块
C. 被修饰的特殊数据区
(1) 全局/静态区
- 核心标志:全局变量 或 static修饰的变量
- 权限:可读写
- 生命周期:程序启动→结束
- 细分:
.data段(初始化数据段)
- 存储:已初始化且值非0的全局/静态变量
- 文件占用:占用可执行文件空间
- 示例:
- int global = 100;
- static int s = 200;
- static int local_static = 300;
.bss段(未初始化数据段)
- 存储:未初始化或初始化为0的全局/静态变量
- 文件占用:不占文件空间,运行时分配并清零
- 示例:
- int global_uninit;
- static int s_zero = 0;
- static int s_uninit;
(2) 常量区 (.rodata段)
- 核心标志:
- 字符串常量
- 全局const常量
- 权限:只读(修改触发段错误)
- 生命周期:程序运行期
- 示例:
- const int MAX = 1000;
- char* str = "Hello";
- const char* PATH = "/home";
3. 关键区别总结
存储位置判断流程:
变量 → 全局/static? → 是 → const? → 是 → .rodata
↓
否 → 已初始化非0? → 是 → .data
↓
否 → .bss
变量 → 全局/static? → 否 → 动态分配? → 是 → 堆区
↓
否 → 栈区
常见混淆点:
- 局部const变量 → 栈区(非.rodata)
- 字符串字面量 → .rodata段
- 字符数组初始化 → 栈区(内容复制到栈)
- static局部变量 → .data/.bss段(非栈区)
权限对比表:
| 段类型 | 权限 | 特点 |
|---|---|---|
| .text段 | 读+执行 | 存储可执行代码 |
| .rodata段 | 只读 | 存储常量数据 |
| .data/.bss段 | 读写 | 存储全局/静态变量 |
| 栈区 | 读写 | 存储局部变量 |
| 堆区 | 读写 | 动态分配内存 |
4. 内存布局(32位Linux示例)
- 高地址 → 低地址
- 内核空间(用户不可访问)
- 栈区(向下生长)
- 内存映射区
- 堆区(向上生长)
- .bss段
- .data段
- .rodata段
- .text段
- 保留区
5. 验证方法
- 打印变量地址观察分布
- 使用size命令查看段大小
- 使用objdump查看详细段信息
- 尝试修改测试权限
实际编程应用
了解内存分区有助于:
- 避免栈溢出问题
- 合理管理堆内存防止泄漏
- 理解变量生命周期
- 优化程序性能
- 调试内存相关错误

浙公网安备 33010602011771号