C/C++的内存布局
2016-06-06 00:34
274 查看
C/C++的内存布局通常有两种说法:一种是堆、栈、全局/静态存储区、自由存储区和常量存储区。另外一种是堆、栈、全局/静态存储区、字符串常量区和代码区。其实更详细准确的说法如下:
1 .rodata段:存放只读数据,比如printf语句中的格式字符串和开关语句的跳转表。也就是你所说的常量区。
例如,全局作用域中的 const int ival = 10,ival存放在.rodata段
再如,函数局部作用域中的printf("Hello world %d\n", c);语句中的格式字符串"Hello world %d\n",也存放在.rodata段
2 .text段:存放已编译程序的机器代码。
注意:程序加载运行时,.rodata段和.text段通常合并到一个Segment(Text Segment)中,操作系统将这个Segment的页面只读保护起来,防止意外的改写。
3 .data段:存放已初始化的全局变量。而局部变量在运行时保存在栈中,既不出现在.data段,也不出现在.bss段中。就是你所说的全局区。
例如:全局作用域中的int ival = 10,static int a = 30,以及局部作用域中的static int b = 30,这3个变量均存放在.data段中。注意,局部作用域中的static变量的生命周期和其余栈变量的生命周期是不同的。
4 .bss段:存放未初始化的全局变量。在目标文件中这个段不占据实际的空间,它仅仅是一个占位符,在加载时这个段用0填充。目标文件区分初始化和未初始化变量是为了空间效率:在目标文件中,未初始化变量不需要占据任何实际的磁盘空间。全局变量如果不初始化则初值为0,同理可以推断,static变量(不管是函数里的还是函数外的)如果不初始化则初值也是0,也分配在.bss段。
例如,全局作用域中的int ival; ival显然存放在.bss段
注意:.data和.bss在加载时合并到一个Segment(Data Segment)中,这个Segment是可读可写的。
5. 栈:函数的参数和局部变量是分配在栈上(但不包括static声明的变量)。在函数被调用时,栈用来传递参数和返回值。由于栈的后进先出特点,所以栈特别方便用来保存/恢复调用现场。
6. 堆:用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)
学习资料参考于: https://www.zhihu.com/question/26224882/answer/32384814
1 .rodata段:存放只读数据,比如printf语句中的格式字符串和开关语句的跳转表。也就是你所说的常量区。
例如,全局作用域中的 const int ival = 10,ival存放在.rodata段
再如,函数局部作用域中的printf("Hello world %d\n", c);语句中的格式字符串"Hello world %d\n",也存放在.rodata段
2 .text段:存放已编译程序的机器代码。
注意:程序加载运行时,.rodata段和.text段通常合并到一个Segment(Text Segment)中,操作系统将这个Segment的页面只读保护起来,防止意外的改写。
3 .data段:存放已初始化的全局变量。而局部变量在运行时保存在栈中,既不出现在.data段,也不出现在.bss段中。就是你所说的全局区。
例如:全局作用域中的int ival = 10,static int a = 30,以及局部作用域中的static int b = 30,这3个变量均存放在.data段中。注意,局部作用域中的static变量的生命周期和其余栈变量的生命周期是不同的。
4 .bss段:存放未初始化的全局变量。在目标文件中这个段不占据实际的空间,它仅仅是一个占位符,在加载时这个段用0填充。目标文件区分初始化和未初始化变量是为了空间效率:在目标文件中,未初始化变量不需要占据任何实际的磁盘空间。全局变量如果不初始化则初值为0,同理可以推断,static变量(不管是函数里的还是函数外的)如果不初始化则初值也是0,也分配在.bss段。
例如,全局作用域中的int ival; ival显然存放在.bss段
注意:.data和.bss在加载时合并到一个Segment(Data Segment)中,这个Segment是可读可写的。
5. 栈:函数的参数和局部变量是分配在栈上(但不包括static声明的变量)。在函数被调用时,栈用来传递参数和返回值。由于栈的后进先出特点,所以栈特别方便用来保存/恢复调用现场。
6. 堆:用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc/free等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)/释放的内存从堆中被剔除(堆被缩减)
学习资料参考于: https://www.zhihu.com/question/26224882/answer/32384814