C程序的内存层次

一个C程序的内存分布可以分为五大部分:代码段、初始化的数据段、未初始化的数据段、栈、堆。

memory layout

注意这里我们讨论的是,在运行一个C编写的二进制程序时,内存是如何分布的。有一些前提知识需要强调。我们都知道,二进制程序原本存在硬盘上,要执行时,会加载进入内存。因为操作系统的作用,虽然一个计算机的内存可能只有4GB,但是操作系统会让每一个程序都以为自己独占了这所有的空间,那么这个时候每一个程序处理的内存地址就是一个虚拟的地址,而不是真实地址。现在我们看见的这个图,就是一个从高地址到低地址的整个4GB空间,所以最上面是0xFFFFFF,最下面是0x000000。

text部分,也就是代码段,存放的是将要执行的机器指令。代码段通常是只读的,不可写入。

已经初始化的数据段,通常也就是我们说的data segment。数据段这里存放了很多虚拟地址,指向程序员在程序中初始化了的全局变量和静态变量。这一部分是可写的。这一块其实可以也分为只读的和可读可写的两块。比如一个全局字符串变量定义:char *string = “hello world”,会把hello world字符串放在只读区域,而string指针则放在可读写的区域。

未初始化的数据段,通常被称为BSS段。这里存放的数据在程序开始执行之前被内核初始化为0。这部分位于数据段后面,包括了所有未初始化或者初始化为0的全局变量和静态变量。例如一个定义:static int i,就会放在BSS段。

栈和堆通常相对生长。栈区域从高地址开始,向低地址生长,是LIFO模式。但是只是x86是这样,有些体系结构是反向生长的!栈指针(SP)用来追踪栈顶,如果入栈或出栈的值,SP的值就会改变。栈中为一个函数调用存入值的总和,叫做栈帧。栈帧最少过也有一个成员,就是返回地址。函数调用时,相关的参数、局部变量、返回地址都会存在栈里。所以C中可以实现递归函数,每次一个递归函数调用自己的时候,就会产生一个新的栈帧,不会影响这个函数之前的实例。

堆使用来动态分配内存的。堆紧接着BSS段开始,从低地址向高地址生长。堆的区域是由malloc、realloc、free函数来处理的,这几个函数可能使用brk和sbrk这样的系统调用来调整大小(也可能是使用mmap实现对不连续的虚拟内存的映射)。堆区域被所有共享库共享,可以在一个进程里动态加载模块。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值