C++ 内存区域
所划分的内存区块有?
在执行 C++ 程序时候,所划分出的内存区块主要有四个:
- 代码区:存放着程序的二进制代码,由操作系统管理。
- 全局区:存放全局变量、静态变量,以及常量(字符常量和
const修饰的全局变量)。 - 栈区:存放所有的局部变量,其空间分配与释放由编译器管理,当函数结束,局部变量自动被释放。
- 堆区:存放所有动态开辟的变量,其空间分配与释放由程序员管理。
在 exe 程序执行前只有代码区和全局区,执行时才具有栈区与堆区。
高地址 (High Address)
+----------------------------------+
| 命令行参数 / 环境变量 |
+----------------------------------+
| |
| 栈 (Stack) |
| |
| 函数局部变量 |
| 函数参数 |
| 返回地址 |
| 引用变量(引用本身通常不存在独立空间)|
| |
| ↓ 向低地址增长 |
+----------------------------------+
(中间空闲区域)
+----------------------------------+
| ↑ 向高地址增长 |
| |
| 堆 (Heap) |
| |
| new / malloc 分配的对象 |
| vector/string内部数据 |
| 智能指针管理的对象 |
| |
+----------------------------------+
+----------------------------------+
| 全局/静态变量区 (.data) |
| |
| 已初始化全局变量 |
| 已初始化 static 变量 |
| |
+----------------------------------+
+----------------------------------+
| BSS 段 (.bss) |
| |
| 未初始化全局变量 |
| 未初始化 static 变量 |
| (程序启动时自动置0) |
+----------------------------------+
+----------------------------------+
| 只读数据区 (.rodata) |
| |
| 字符串常量 |
| const 全局对象(通常) |
| constexpr 数据 |
+----------------------------------+
+----------------------------------+
| 代码区 (.text) |
| |
| 函数代码 |
| 类成员函数 |
| main() |
+----------------------------------+
低地址 (Low Address)
代码区解析
代码区里面存放的是 .exe 二进制机器指令,具有两个特性:
- 共享性:内存中只有一份程序代码,多个进程/线程可共享,节约空间。
- 只读性:不允许被修改。
全局区解析
全局区存的是全局变量、静态变量以及常量,下面通过示例演示。
1 全局变量的地址
1 |
|
运行可见全局变量的地址通常很接近(在同一内存段)。
2 静态变量的地址
1 |
|
静态变量与全局变量的地址也会非常接近,因为它们都存在全局区域。
3 常量(字符常量及 const 全局常量)
1 |
|
可以看到全局常量与全局变量通常位于同一或相近的内存区段。
栈区解析
栈区存放的是局部变量,下面通过对比展示全局与局部变量地址差异。
1 普通局部变量
1 |
|
局部变量地址与全局变量地址差距较大,说明全局区与栈区是不同区域。
2 const 修饰局部变量
1 |
|
全局 const 常量与局部 const 常量所属区域可能不同,局部 const 常量通常属于栈区。
3 栈区注意事项
栈区里的变量不可返回其地址(返回后该栈空间可能会被释放)。
1 |
|
某些编译器(例如文中提到的 VS2019)在某些情况下可能会让第一次错误使用看似“成功”,但这是未定义行为,不可依赖。
堆区解析
堆区的开辟与释放由程序员自己执行,开辟一般用 new,释放一般用 delete。
1 |
|
堆区变量在 delete 之前其值不受函数返回影响。
new 的用法
1 开辟单个堆区元素
语法
- 开辟:
type* name = new type(content);其中type是元素类型,content是元素内容,name是变量名。 - 释放:
delete name。
1 |
|
2 开辟数组
语法
- 开辟:
type* name = new type[size]; - 释放:
delete [] name(必须带方括号)。
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 逸人の博客!
评论
