648 字
3 分钟
内存空间
内存空间
- 代码区:存储机器指令。共享且只读
- 全局/静态存储区:存储全局变量和类的静态变量。这些变量在整个程序运行期间都会存在,但是它们的可见性和生命周期取决于作用域。
- 常量区
.rodata
:存储常量数据,字面值数据,只读无法修改。 - 栈:存储函数的局部变量、参数、返回地址等数据。
- 堆:存储程序员手动分配的数据,如new、malloc等。
下面用代码来举例:
#include <iostream>#include <vector>
int global_var = 1; // 全局区
int* const cp1 = &global_var; // 常量区(全局常量数据)const int ci = 3; // 常量区
class Animal {public: static int weight; // 静态区 static const int age; // 常量区(静态常量数据)};
int Animal::weight = 0; // 静态区const int Animal::age = 0; // 常量区
int main() { // 栈区 int* const cp2 = &global_var; // 栈区(常量指针) int animal_num = 5; // 栈区 std::vector<Animal> animals(animal_num); //栈区 + 堆区}
常量数据:
- 全局常量数据通常存储在
.rodata
中,而不是全局区中。- 类内的静态常量数据存储在
.rodata
中,- 局部常量数据,编译器不会存储在
.rodata
中,而是直接存储在栈中。
animals
分为vector元数据
和data
两个部分,分别存储在栈和堆中。
内存对齐
代码:
#include <iostream>#include <string>
int main(){ int a = 123; int* m = &a; // 指针类型 std::cout << "a address: " << &a << std::endl; std::cout << "m address: " << &m << std::endl; return 0;}
输出如下:
a address: 0000008D746FFB84m address: 0000008D746FFBA8
为什么m与a的内存相差为36字节,不是32字节的int数据?
知识点:堆栈内存的分布,除了受到分配的相对顺序和变量大小的影响,还受到内存对齐规则的影响。
首先,栈中的内存按照a, m, i
的顺序分配内存空间。
为了提高内存访问效率,编译器通常会遵循内存对齐规则,不同了类型的数据对齐的边界大小不同。
int
类型通常为4
字节- 64位系统中,指针类型为
8
字节
a
的起始地址为xx84
,分配32字节后的内存地址为xxA4
,显然不是8的倍数。
m
为指针类型,按照内存对齐规则需要从8
的倍数开始,因此需要空出4
字节内存空间,从xxA8
开始分配m
的内存。
因此:a与m的地址相差32 + 4 = 36
字节,包括32
字节的int数据,和4
字节的对齐空间。