变量的存储布局
了解不同变量在内存中的存储布局,对于程序员是很重要的,我们看下面一段程序:
#include <stdio.h>
const int A = 10;
int a = 20;
static int b = 30;
int c;
int main(void)
{
static int a = 40;
char b[] = "Hello world";
register int c = 50;
printf("Hello world %d\n", c);
return 0;
}
我们编译之后用readelf命令看它的符号表,了解各变量的地址分布,具体操作如下:

我们截取我们所关心的部分:
Num: Value Size Type Bind Vis Ndx Name
12: 0000000000004014 4 OBJECT LOCAL DEFAULT 25 b
13: 0000000000004018 4 OBJECT LOCAL DEFAULT 25 a.0
31: 0000000000002004 4 OBJECT GLOBAL DEFAULT 18 A
34: 0000000000004020 4 OBJECT GLOBAL DEFAULT 26 c
35: 0000000000004010 4 OBJECT GLOBAL DEFAULT 25 a
Section Headers:
[Nr] Name Type Address Offset Size
[16] .text PROGBITS 0000000000001080 00001080 0000000000000154
[18] .rodata PROGBITS 0000000000002000 00002000 0000000000000018
[25] .data PROGBITS 0000000000004000 00003000 000000000000001c
[26] .bss NOBITS 000000000000401c 0000301c 000000000000000c
(1)变量A用const修饰,可以看到其位于.rodata段,我们可以通过hexdump -C a.out

可以看到字符串”hello world”也分配在rodata段,说明字符串字面值是只读的,相当于在全局作用域定义了一个const数组
(2)而.data段可以看到从0000000000004000开始,size是1C,也就是到000000000000401C结束,在这个范围内,我们有三个变量:a, b, a.0
a是一个GLOBAL的符号,而b被static关键字修饰了,导致它成为一个LOCAL的符号,所以static在这里的作用是声明b这个符号为LOCAL的,不被链接器处理,链接器会在之后文章进行说明。总之也就是说,一个函数定义前面也可以用static修饰,表示这个函数名符号是LOCAL的, a.0是什么呢?它就是main函数中的static int a。
-
函数中的static变量不同于以前我们讲的局部变量,它并不是在调用函数时分配,在函数返回时释放,而是像全局变量一样静态分配
-
函数中的static变量只在函数中起作用,比如main函数中的a这个变量名只在main函数中起作用,在别的函数中说变量a就不是指它了,所以编译器给它的符号名加了一个后缀,变成a.0,以便和全局变量a以及其它函数的变量a区分开
(4)bss段从000000000000401c开始,仅有一个变量c,在这个段,进程会为bss段开辟内存空间,并清零
(5)现在还有register int c = 50 以及 char b[] = “Hello world”没有分析。而函数的参数和局部变量是分配在栈上的。我们来查看反汇编代码:

-
可见,给
b初始化用的这个字符串"Hello world"并没有分配在.rodata段,而是直接写在指令里了,通过三条指令把12个字节写到栈上 -
变量
c并没有在栈上分配存储空间,而是直接存在eax寄存器里,后面调用printf也是直接从eax寄存器里取出c的值当参数压栈,这就是register关键字的作用,指示编译器尽可能分配一个寄存器来存储这个变量
总结:
-
bss段:用来存放程序中未初始化的全局变量的内存区域,属于静态内存分配
-
data段:用来存放程序中已初始化的全局变量的内存区域,属于静态内存分配
-
text段:用来存放程序执行代码的内存区域
-
rodata段:存放只读数据,比如字符串常量、全局const变量(注意并非所有常量都会被保存在rodata段中)
-
栈:用户程序临时创建的局部变量
-
堆:用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减, 需要通过new,malloc分配自己手动申请, 通过free自己手动释放
更多推荐



所有评论(0)