C++内存分配

环境

ubuntu 16.04 64
g++ 6.3

实例文件

tes.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//#include <iostream>

using namespace std;

int global_a; //.bss
int global_b = 0; //.bss
int global_c = 3; //.data
static int static_global_a; //.bss
static int static_global_b = 3; //.data
const int const_global_a = 0; //.rodata
const int const_global_b = 1; //.rodata
const static int const_static_global_a = 0; //.rodata
const static int const_static_global_b = 1; //.rodata

int main() {
static int local_static_a; //.bss
static int local_static_b = 3; //.data
const static int local_const_static_a = 0; //.rodata
const static int local_const_static_b = 1; //.rodata
const int local_const_a = 0;
const int local_const_b = 1;
int local_a;
return 0;
}

相关命令

1
2
3
4
5
g++-6 -c tes.cpp -o tes.o
size tes.o
objdump -CS -s -j .data tes.o
readelf -all tes.o
nm ./a.out

步骤

编译单个tes.cpp文件

1
2
g++-6 -c tes.cpp -o tes.o
g++-6 tes.cpp

查看大小

1
2
3
X@DESKTOP-LMTTY:~/test$ size tes.o
text data bss dec hex filename
105 12 16 129 81 tes.o

反编译查看各分区

.data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
X@DESKTOP-LMTTY:~/test$ objdump -CS -s -j .data tes.o

tes.o: file format elf64-x86-64

Contents of section .data:
0000 03000000 03000000 03000000 ............

Disassembly of section .data:

0000000000000000 <global_c>:
0: 03 00 00 00 ....

0000000000000004 <static_global_b>:
4: 03 00 00 00 ....

0000000000000008 <main::local_static_b>:
8: 03 00 00 00 ....

.bss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
X@DESKTOP-LMTTY:~/test$ objdump -CS -s -j .bss tes.o

tes.o: file format elf64-x86-64


Disassembly of section .bss:

0000000000000000 <global_a>:
0: 00 00 00 00 ....

0000000000000004 <global_b>:
4: 00 00 00 00 ....

0000000000000008 <static_global_a>:
8: 00 00 00 00 ....

000000000000000c <main::local_static_a>:
c: 00 00 00 00 ....

.rodata

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
X@DESKTOP-LMTTY:~/test$ objdump -CS -s -j .rodata tes.o

tes.o: file format elf64-x86-64

Contents of section .rodata:
0000 00000000 01000000 00000000 01000000 ................
0010 00000000 01000000 ........

Disassembly of section .rodata:

0000000000000000 <const_global_a>:
0: 00 00 00 00 ....

0000000000000004 <const_global_b>:
4: 01 00 00 00 ....

0000000000000008 <const_static_global_a>:
8: 00 00 00 00 ....

000000000000000c <const_static_global_b>:
c: 01 00 00 00 ....

0000000000000010 <main::local_const_static_a>:
10: 00 00 00 00 ....

0000000000000014 <main::local_const_static_b>:
14: 01 00 00 00 ....

查看符号表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
X@DESKTOP-LMTTY:~/test$ nm tes.o
0000000000000000 B global_a
0000000000000004 B global_b
0000000000000000 D global_c
0000000000000000 T main
0000000000000000 r _ZL14const_global_a
0000000000000004 r _ZL14const_global_b
0000000000000008 b _ZL15static_global_a
0000000000000008 r _ZL21const_static_global_a
000000000000000c r _ZL21const_static_global_b
000000000000000c b _ZZ4mainE14local_static_a
0000000000000004 d _ZZ4mainE14local_static_b
0000000000000010 r _ZZ4mainE20local_const_static_a
0000000000000014 r _ZZ4mainE20local_const_static_b

nm解释参考http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/nm.html

总结

C++中内存从低地址到高地址分别为:

  1. .text segment: 代码段
  2. .rodata segment: 存储常量,例如字符串常量,const修饰的变量。
  3. .data segment: 又称GVAR.存储已经初始化的非零全局变量和静态变量(全局/局部)
  4. .bss segment: BSS segment也称为未初始化的数据段,包含全局或静态未初始化的变量,该部分数据中的值会在程序启动时直接初始为0,BSS是Block Started by Symbol的简写
  5. heap: 堆,动态内存区域,使用malloc或new申请的内存.向地址变大的方向增长.
  6. 自由存储区: 未使用的内存
  7. stack: 栈,局部变量、参数、返回值都存在这里,函数调用开始会参数入栈、局部变量入栈;调用结束依次出栈。向地址变小的方向增长.

参考

实例分析C++内存布局
C/C++中已初始化/未初始化全局/静态/局部变量/常量在内存中的位置
https://en.wikipedia.org/wiki/Data_segment