C程序内存分布(译)

来源:互联网 发布:mac网络图 编辑:程序博客网 时间:2024/05/22 04:38


C程序内存分布


一个典型的C程序内存分布包括以下几个方面

1. 代码区 Text segment
2. 初始化数据区  Initialized data segment
3. 未初始化数据区  Uninitialized data segment
4. 栈区 Stack
5. 堆区  Heap


一个典型的运行时程序内存分布

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-layouttext       data        bss        dec        hex    filename960        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-layouttext       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-layouttext       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-layouttext       data        bss        dec        hex    filename960         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-layouttext       data        bss        dec        hex    filename960         256          8       1224        4c8    memory-layout



##博客仅作个人记录##

0 0
原创粉丝点击