648 字
3 分钟
内存空间
2025-01-07

内存空间#

  • 代码区:存储机器指令。共享且只读
  • 全局/静态存储区:存储全局变量和类的静态变量。这些变量在整个程序运行期间都会存在,但是它们的可见性和生命周期取决于作用域。
  • 常量区.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: 0000008D746FFB84
m 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字节的对齐空间。

内存空间
https://chrisnake11.github.io/blog/posts/coding/c基础/01内存空间/
作者
Zheyv
发布于
2025-01-07
许可协议
CC BY-NC-SA 4.0