一个典型的C程序内存分布包括以下几个方面
1. 代码区 Text segment
2. 初始化数据区 Initialized data segment
3. 未初始化数据区 Uninitialized data segment
4. 栈区 Stack
5. 堆区 Heap
![Memory-Layout](http://d1hyf4ir1gqw6c.cloudfront.net//wp-content/uploads/Memory-Layout-300x255.gif)
一个典型的运行时程序内存分布
1. 代码区 Text Segment:
文本区,也被称为代码区,是程序在目标文件或者内存里面的一段区域, 包含可执行的指令。
作为一段内存区域,代码区通常被放置在堆栈的下面,防止被堆栈的溢出覆盖,导致出错。
通常,代码区是可以共享的,频繁运行的程序也只有一份拷贝留存在内存里面, 比如文本编辑器,C编译器,Shell 等等。此外, 代码区也通常是只读的,以防止被程序意外的改变运行指令。
2. 初始化数据区 Initialized Data Segment:
初始化数据区,也被简单称为数据区。 数据区是程序虚拟地址空间的一部分,包含初始化过的全局变量和静态变量。
注意,数据区不是只读的,变量值可以在运行时改变。
数据区可以被进一步分为只读数据区和读写数据区。 比如,全局字符串变量 char s[] = “hello world” 和 全局整形变量 int debug =1 存储在读写数据区,而 全局变量 const char* string = “hello world” 就不一样了,字符串文本 “hello world” 被存储在只读数据区,字符指针则被存储在读写数据区。
3. 未初始化数据区 Uninitialized Data Segment:
未初始化数据区,通常被称为“bss”区, 名字来自于一个古老的汇编操作 “block started by symbol.”。 在程序开始执行之前,这一区的数据会被系统(内核)初始化成0。
未初始化数据区位于初始化数据区的下面,包含所有的未初始化或者初始化为0的全局变量和静态变量。
4. 栈区 Stack:
栈区通常是和堆区放在一起相向增长(栈向下增长,堆向上增长),当栈指针和堆指针相遇时,空闲空间就耗尽了。
栈区域包括程序栈,一个LIFO结构,通常位于高地区内存区域。在标准x86计算机结构下,栈向地址0增长,在一些其他的计算机结构,也可能是反向增长。栈指针寄存器指向栈顶,每次有值压栈时,栈指针寄存器跟着相应变化。一次函数调用压入的一组值被称之为“栈帧“,一个“栈帧“里面至少包括一个返回地址。
栈是用来存储局部变量的地方,也存储每次函数调用时的信息。当有函数被调用时,返回地址以及调用者的现场信息(寄存器信息等)被存在栈里,被调用函数则需要为它自己的局部变量在栈上分配空间。递归函数在C里面的调用方式就是这样,当递归函数调用自身时,一个新的栈帧被使用,因此这组变量不会干扰之前调用函数里面的值。
5. 堆区 Heap:
堆通常是用来存储动态分配的内存区域,位于BSS区的上方,向高地址方向增长。堆区由函数malloc, realloc, and free(通常对应于brk, sbrk 系统调用)管理。堆区对进程内所有的共享库和动态加载模块是共享的。
下面用几个例子来说明》
函数size()用来计算一个程序不同区域段的大小,更多详情可以参考man page, size(1).
Examples.
The size(1) command reports the sizes (in bytes) of the text, data, and bss segments. ( for more details please refer man page of size(1) )
1. 让我们从一个简单的例子开始
#include <stdio.h>
int main(void)
{
return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 248 8 1216 4c0 memory-layout
2. 我们增加一个全局变量,现在再来看bss段大小
#include <stdio.h>
int global;/* Uninitialized variable stored in bss*/
int main(void)
{
return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 248 12 1220 4c4 memory-layout
3. 我们再来增加一个未初始化的静态变量,观察一下bss段的变化.
#include <stdio.h>
int global;/* Uninitialized variable stored in bss*/
int main(void)
{
static int i; /* Uninitialized static variable stored in bss */
return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 248 16 1224 4c8 memory-layout
4. 让我们把这个静态变量初始化,再观察一下data和bss段的变化
#include <stdio.h>
int global;/* Uninitialized variable stored in bss*/
int main(void)
{
static inti = 100; /* Initialized static variable stored in DS*/
return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 252 12 1224 4c8 memory-layout
5. 我们把全局变量也初始化,再次观察data和bss段
#include <stdio.h>
int global = 10; /* initialized global variable stored in DS*/
int main(void)
{
staticint i = 100; /* Initialized static variable stored in DS*/
return 0;
}
[narendra@CentOS]$ gcc memory-layout.c -o memory-layout
[narendra@CentOS]$ size memory-layout
text data bss dec hex filename
960 256 8 1224 4c8 memory-layout
##博客仅作个人记录##