C++ 程序内存分区
C 程序运行时操作系统会给进程分配虚拟地址空间在 32/64 位系统中逻辑上划分为代码区、全局静态区、常量区、栈区、堆区5 个区域。下面从存储内容、管理方式、生命周期、权限、代码示例、常见坑逐一拆解。一、代码区Text 段 / 只读代码段1. 存储内容编译后生成的二进制机器指令包括所有函数的执行代码main函数、自定义函数、库函数。2. 核心特点只读防止程序运行时指令被篡改避免崩溃可共享多个运行相同程序的进程共用同一份代码区节省内存地址低程序启动时加载程序结束才释放。3. 易错点不能修改代码区内容比如修改函数指令会直接触发段错误。二、全局 / 静态区Data 段 BSS 段存放全局变量和 **static静态变量 **整个程序生命周期有效程序结束由系统回收。分为两个子段1. Data 段已初始化全局区存储初始化的全局变量、初始化的静态局部 / 全局变量cpp运行int g_val 100; // 全局变量 → Data段 void func() { static int s_val 200; // 静态局部变量 → Data段**不在栈区** }2. BSS 段未初始化全局区存储未初始化的全局变量、未初始化的静态变量特点程序加载时系统自动将该区域全部置 0不占用磁盘空间运行时才分配内存。cpp运行int g_none; // 未初始化全局变量 → BSS段默认0 static int s_none; // 静态未初始化 → BSS段3. 关键易错点static修饰的局部变量生命周期是全局的但作用域仅在函数内静态变量只会初始化 1 次函数多次调用不会重复初始化。三、常量区只读数据段1. 存储内容字符串字面量hello全局const修饰的常量只读的静态常量。2. 核心特点只读权限强行修改直接报段错误 (Segmentation Fault)生命周期和程序一致。3. 代码示例 坑点cpp运行// 字符串abc存在常量区str存的是常量区地址 char *str abc; str[0] x; // ❌ 错误修改常量区直接崩溃 const char str2[] abc; // 数组字符串拷贝到栈上可修改 str2[0] x; // ✅ 正确重点区分char* str指向常量区char str[]在栈区。四、栈区Stack1. 存储内容局部变量函数内定义的普通变量函数参数、函数返回地址函数调用时的临时上下文。2. 管理方式系统自动分配、自动释放无需程序员干预。函数调用时栈向下扩展分配内存函数执行结束栈自动回收内存释放。3. 核心特点空间小Windows 默认 1MLinux 默认 8M速度极快连续内存CPU 直接寻址结构先进后出栈结构内存连续大小固定不能动态扩容。4. 常见问题栈溢出递归深度太大、定义超大数组int arr[10000000]直接崩溃局部变量出函数后销毁不能返回局部变量的地址。cpp运行int* test() { int a 10; // a在栈区函数结束销毁 return a; // ❌ 错误返回栈地址野指针 }五、堆区Heap1. 存储内容程序员动态申请的内存通过new / malloc开辟。2. 管理方式完全手动管理申请new/malloc释放delete/free忘记释放 →内存泄漏释放后继续使用 →野指针。3. 核心特点空间极大受虚拟内存限制内存不连续分配速度比栈慢生命周期由程序员控制不释放则一直存在程序结束系统回收。4. 代码示例cpp运行int* p new int(10); // 堆区开辟int值10 delete p; // 手动释放 int* arr new int[5]; // 堆数组 delete[] arr;5. 易错点new[]必须用delete[]普通new用delete不能混用释放后指针置空p nullptr避免野指针。五大内存分区对比总表表格分区管理方式存储内容生命周期读写权限典型问题代码区系统二进制指令、函数程序全程只读指令篡改崩溃全局静态区系统全局 / 静态变量程序全程读写静态变量全局存活常量区系统字符串常量、全局 const程序全程只读修改直接段错误栈区自动分配释放局部变量、参数函数内读写栈溢出、野指针堆区手动 new/delete动态内存手动控制读写内存泄漏、野指针补充完整代码演示可直接运行观察cpp运行#include iostream using namespace std; int g_val 10; // 全局区 Data段 int g_none; // 全局区 BSS段 const char* g_str hello; // 常量区 void test() { static int s_val 20; // 静态局部变量 → 全局区 int a 30; // 栈区 int* p new int(40); // 堆区 delete p; } int main() { test(); return 0; }