C程序的内存布局分析

C 程序的典型内存由以下部分组成:

  1. 文本段(text)
  2. 初始化数据段 (data)
  3. 未初始化数据段(bss)
  4. 堆 (heap)
  5. 栈(stack)

典型内存布局:

1.文本段: 文本段,也称为代码段或简称为文本,是目标文件或内存中的程序部分之一,其中包含可执行指令。作为内存区域,文本段可以放置在堆或堆栈下方,以防止堆和堆栈溢出覆盖它。 通常,文本段是可共享的,因此对于频繁执行的程序(例如文本编辑器、C 编译器、shell 等),内存中只需要保留一个副本。此外,文本段通常是只读的,以防止程序意外修改其指令。

2.初始化数据段: 初始化数据段,通常简称为数据(data)段。数据段是程序虚拟地址空间的一部分,其中包含由程序员初始化的全局变量和静态变量。请注意,数据段不是只读的,因为变量的值可以在运行时更改。该段又可以分为初始化只读区和初始化读写区。
例如,C 中 char s[] = “hello world” 定义的全局字符串以及 main(即全局)之外的 int debug=1 这样的 C 语句将存储在初始化的读写区域中。而像 const char* string = “hello world” 这样的全局 C 语句使得字符串文字“hello world”存储在初始化的只读区域中,而字符指针变量 string 存储在初始化的读写区域中。
例如: static int i = 10 将存储在数据段中,全局 int i = 10 也将存储在数据段中

3. 未初始化数据段: 未初始化数据段通常称为“ bss ”段,以一个古老的汇编运算符命名,代表“由符号开始的块”。该段中的数据在程序开始执行之前被内核初始化为算术0。未初始化的数据从数据段末尾开始,包含所有初始化为零或源代码中没有显式初始化的全局变量和静态变量。
例如,声明一个变量 static int i; 将包含在 BSS 段中。 
例如,声明了一个全局变量 int j;将包含在 BSS 段中。

4. 栈: 栈区传统上与堆区相邻,并以相反的方向增长;当堆栈指针遇到堆指针时,可用内存就耗尽了。利用现代的大地址空间和虚拟内存技术,它们几乎可以放置在任何地方,但它们通常仍然以相反的方向增长。堆栈区域包含程序堆栈,一种后进先出的结构,通常位于内存的较高部分。在标准PC x86计算机架构上,它向地址零增长;在其他一些架构上,它以相反的方向增长。“堆栈指针”寄存器跟踪堆栈顶部;每次将值“推入”堆栈时都会对其进行调整。为一个函数调用推送的一组值称为“堆栈帧”;堆栈帧至少包含一个返回地址。堆栈,存储自动变量以及每次调用函数时保存的信息。每次调用函数时,返回位置的地址以及有关调用者环境的某些信息(例如一些机器寄存器)都保存在堆栈中。然后,新调用的函数在堆栈上为其自动变量分配空间。这就是 C 中的递归函数的工作原理。每次递归函数调用自身时,都会使用一个新的堆栈帧,因此一组变量不会干扰函数另一个实例中的变量。

5. 堆: 堆是通常发生动态内存分配的段。堆区域从 BSS 段的末尾开始,并从那里增长到更大的地址。堆区域由 malloc、realloc 和 free 管理,它们可以使用 brk 和 sbrk 系统调用来调整其大小(请注意,使用 brk/sbrk 和单个“堆区域”并不需要履行合同malloc/realloc/free;它们也可以使用 mmap 来实现,以将虚拟内存的潜在非连续区域保留到进程的虚拟地址空间中)。堆区域由进程中的所有共享库和动态加载的模块共享。

以下是一个说明的例子:

#include <stdio.h>

static unsigned int val1 = 1;        //val1存放在.data段
unsigned int val2 = 1;               //初始化的全局变量存放在.data段
unsigned int val3 ;                  //未初始化的全局变量存放在.bss段
const unsigned int val4 = 1;         //val4存放在.rodata(只读数据段)

unsigned char Demo(unsigned int num) //num 存放在栈区
{
  char var = "123456";               //var存放在栈区,"123456"存放在常量区
  unsigned int num1 = 1 ;            //num1存放在栈区
  static unsigned int num2 = 0;      //num2存放在.data段
  const unsigned int num3 = 7;       //num3存放在栈区
  void *p;
  p = malloc(8);                     //p存放在堆区
  free(p);
  return 1;
}

void main()
{
  unsigned int num = 0 ;
  num = Demo(num);                   //Demo()函数的返回值存放在栈区。
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流浪_彩虹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值