以下是优化后的内容,结合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对象
栈区 编译器自动管理 函数作用域 局部变量/参数