【C++学习】内存分区模型
Published in:2024-08-12 | category: C++
Words: 1.2k | Reading time: 4min | reading:

C++程序在执行时,将内存大方向划分位4个区域

  • 代码区: 存放函数体的二进制代码,由操作系统进行管理的
  • 全局区: 存放全局变量和静态变量以及常量
  • 栈区: 由编译器自动分配释放,存放函数的参数值,局部变量等
  • 堆区: 由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
    意义: 不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程

程序运行前

在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域:

代码区

存放CPU执行的机器指令

  • 代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可
  • 代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

全局区

全局变量、静态变量字符串常量和其他常量存放在此

该区域的数据在程序结束后由操作系统释放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

// 全局变量

int g_a = 10;
int g_b = 10;

// 全局常量

const int c_g_a = 10;
const int c_g_b = 10;


int main() {

// 局部变量
int a = 10;
int b = 10;
// 打印地址
cout << "局部变量a地址为:" << (int)&a << endl;
cout << "局部变量b地址为:" << (int)&b << endl;

cout << "全局变量g_a地址为:" << (int)&g_a << endl;
cout << "全局变量g_b地址为:" << (int)&g_b << endl;

// 静态变量
static int s_a = 10;
static int s_b = 10;

cout << "静态变量s_a地址为:" << (int)&s_a << endl;
cout << "静态变量s_b地址为:" << (int)&s_b << endl;

cout << "字符串常量地址为:" << (int)&"hello world" << endl;
cout << "字符串常量地址为:" << (int)&"hello world1" << endl;

cout << "全局常量c_g_a地址为:" << (int)&c_g_a << endl;
cout << "全局常量c_g_b地址为:" << (int)&c_g_b << endl;

const int c_l_a = 10;
const int c_l_b = 10;
cout << "局部常量c_l_a地址为:" << (int)&c_l_a << endl;
cout << "局部常量c_l_b地址为:" << (int)&c_l_b << endl;


system("pause");

return 0;
}

x64(64位):

x86(32位):

Q: 为什么当vs管理器为x64(64位)时,a的地址比b小32,但是管理器改为x86(32位)时,a比b地址大12

  • x64架构(64位)
    1. 栈对齐:x64架构通常要求栈对齐到16字节或32字节边界,以优化性能并满足某些指令集的要求。这可能导致在局部变量之间插入额外的填充(padding)。
    2. 调用约定:在x64架构下,函数调用时可能需要在栈上保留更多的空间用于寄存器保存区域(callee-saved registers)和其他目的。这可能导致局部变量之间的地址差异大于它们的大小。
    3. 优化:编译器可能会在64位模式下执行更积极的优化,这可能会影响变量的布局。
    4. 局部变量大小:即使局部变量是int类型,它们在栈上的布局也可能会受到其他因素的影响,如调用约定、栈对齐等。

在x64架构下,32字节的差异可能是由于编译器在ab之间插入了对齐填充,或者由于其他局部变量或保留空间的布局。

  • x86架构(32位)
    1. 栈对齐:x86架构通常要求栈对齐到4字节边界,这意味着局部变量之间的地址差异通常是它们大小的整数倍。
    2. 调用约定:在x86架构下,函数调用时在栈上保留的空间通常比x64架构少,因此局部变量之间的地址差异可能更小。
    3. 优化:编译器在32位模式下的优化可能与64位模式不同,这可能会影响变量的布局。
      在x86架构下,12字节的差异可能是因为:
      • ab之间可能有其他局部变量或对齐填充。
      • 编译器可能为了保持栈对齐而插入填充。
      • 由于某些优化,编译器可能改变了局部变量的顺序或布局。

程序运行前

栈区

由编译器自动分配释放,存放函数的参数值,局部变量等

注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

示例:

1
2
3
4
5
6






Prev:
我是一个分界线
Next:
【C++学习】结构体