跳转至

Memory Model

  • 单线程下:对象在内存中如何存在、何时开始/结束生命周期、哪些访问是合法的
  • 多线程下:不同线程看到同一块内存时,读写如何同步、什么叫数据竞争、编译器和 CPU 可以做哪些重排

C++ 对象按存储期大致分为 4 类:

  1. 自动存储期:函数内局部变量,进入作用域构造,离开作用域析构
  2. 静态存储期:全局变量、命名空间静态、函数内静态。程序启动到结束都可能存在
  3. 线程存储期:thread_local,每个线程一份实例
  4. 动态存储期:new/malloc 得到的内存,需手动释放或交给 RAII 管理

内存区域:

  1. 栈:存放函数调用上下文和自动变量,分配释放极快,由编译器和调用约定自动管理
  2. 堆:运行时动态分配的大块区域,生命周期灵活,但管理成本高,容易泄漏和碎片
  3. 全局/静态区:存放全局变量、静态变量,生命周期贯穿程序运行期
  4. 常量区(只读数据区):字符串字面量、只读常量等,通常不可写
  5. 代码区(文本段):机器指令本体

stack(栈):

  1. 分配释放由函数进出作用域自动完成。一般是连续内存,局部性好,速度快。空间通常较小(和平台、线程栈大小配置有关)
  2. 放函数参数、返回地址、保存寄存器。自动存储期局部变量(普通局部对象)
  3. 栈溢出:递归过深或大数组放栈上
  4. 悬空指针:返回局部变量地址

heap(堆):

  1. 运行时按需申请,大小和生命周期更灵活。分配释放慢于栈。可能出现内存碎片。需要正确管理所有权
  2. 放动态创建对象,大体量数据或跨作用域共享对象
  3. 内存泄漏:只分配不释放
  4. 重复释放:同一块内存释放多次
  5. 野指针:释放后继续访问
  6. 异常路径泄漏:中途抛异常没走到释放逻辑

全局/静态区:

  1. 放全局变量,静态变量(包括函数内静态),类静态数据成员
  2. 程序启动前初始化,程序退出时析构

常量区:字符串字面量通常在只读区域。试图修改会导致未定义行为或崩溃

代码区:存程序指令。一般可执行不可写(受平台保护策略影响)

评论区

欢迎在评论区指出文档错误,为文档提供宝贵意见,或写下你的疑问