C语言的内存布局(详细分析变量在.bss和DS段的分布)

  • 引言

随着深入的学习C语言,这门语言是与内存息息相关的,那么为了更好地认识这门语言,我们就要从内存深入剖析,此篇博客来浅谈一下C语言的内存布局。

  • 从内存布局谈起

  1. 运行中的C语言内存布局
    在这里插入图片描述
    上图中显示了,C语言的内存布局,可以看到的区域有,文本段,初始化数据端、未初始化数据段,还有堆与栈。
  2. 分析各段作用

(1) 文本段(.text)

文本段,也叫作代码段;是目标文件(二进制文件)或内存中包含可执行程序的一部分。作为存储区,文本段放在堆和栈区下面,以防止堆栈溢出覆盖它。文本段通常是only read(仅仅可读),就是为防止程序意外修改其中的指令。

(2)初始化数据段(.data)

初始化数据段,通常被叫做,数据段;数据段是程序的虚拟地址空间的一部分,其中包含由人们初始化的全局变量和静态变量。这段的数据不是仅仅可读的,因为变量的值可以在运行时修改它们的值。
对该段又可以细分为:初始化的只读区域和初始化的读写区域
举例说明:
C语言中定义全局变量char arr[] = “hello world~~”; 再定义局部变量char arr1[] = “hello world~~”; 二者都将存储在初始化读写区域中;但是如果像这样定义全局变量,const char *string = “hello world~~”; 那么将存储在初始化只读区域中,而字符串指针变量将存储在初始化读写区域中。
(3)未初始化数据段(.dss)

未初始化数据段,通常叫做“bss”段;在该段中将放置未初始化的静态变量和未初始化的指针,并且初始化为0和空指针。未初始化的数据从数据段的末尾开始,包含初始化为0或者没有初始化的全局变量和静态变量;
举例说明:(都未初始化)

  1 #include <stdio.h>
  2 static int j;
  3 int i;
  4 int main(){
  5     static int k;
  6     printf("%d %d %d\n", i, j, k);
  7     return 0;
  8 }

输出:
在这里插入图片描述

  • 用代码验证(数据在.bss与数据段DS中的存储)

我们将使用一个开发工具—size;来观察内存分布情况

 1 #include <stdio.h>
  2 
  3 int main(){
  4 
  5     return 0;
  6 }

在这里插入图片描述
接着,在程序中添加一个全局变量,现在检查.bss的大小

  1 #include <stdio.h>
  2 
  3 int global; //未初始化全局变量存储在.bss中
  4 
  5 int main(){
  6 
  7     return 0;
  8 }

在这里插入图片描述
对比前后变化,发现.bss发生了变化。

我们再来添加一个未初始化静态变量,它也存储在.bss中

  1 #include <stdio.h>
  2 
  3 int global; //未初始化全局变量存储在.bss中
  4 
  5 int main(){
  6 
  7     static int i;   //未初始化的静态变量存储在.bss值被初始化为0 
  8     
  9     static int j;   //未初始化的静态变量存储在.bss值被初始化为0 
 10     return 0;
 11 }


在这里插入图片描述
现在我们初始化,静态变量的值,将存储字数据段中

  1 #include <stdio.h>
  2 
  3 int global; //未初始化全局变量存储在.bss中
  4 
  5 int main(void){
  6 
  7     static int i = 100; //初始化的静态变量存储在数据段
  8 
  9     static int j = 100; //初始化的静态变量存储在数据段
 10     return 0;
 11 }

在这里插入图片描述
可以看到,.bss变小,.data变大;

我们再来给全局变量初始化,观察情况:

  1 #include <stdio.h>
  2 
  3 int global = 100; //初始化全局变量存储在数据段中
  4 
  5 int main(void){
  6 
  7     static int i = 100; //初始化的静态变量存储在数据段
  8 
  9     static int j = 100; //初始化的静态变量存储在数据段
 10     return 0;
 11 }

在这里插入图片描述
相信通过以上的分析,可以直观的看到数据是如何在.bss和data中存储的。

(4)堆栈

普通的局部变量在栈空间上分配。
堆栈区一般与堆区(heap)相邻,并且向相反的方向(低地址)增长;当堆栈指针与堆指针相遇时,可用的内存表示耗尽。堆栈区域包含程序堆栈,LIFO结构,通常位于内存比较高的地方。
堆栈区发生C语言中的函数调用,当函数调用返回地址和有关调用的信息都保存在堆栈区;接着新调用的函数在堆栈上方为其自动和临时变量分配空间,这就是C语言递归函数的工作方式。每次递归函数调用自身,都会使用新的堆栈帧,因此一组变量不会干扰来自函数的另一个实例中的变量。

(5)堆

堆区是经常发生动态内存分配的区域。堆区从.bss的末尾开始,并从末尾增长到更大的地址。(堆区由malloc,realloc和free管理,可以使用brk和sbrk系统调用来调整其大小也可以使用mmap实现。)

  • 最后

由于本人也是初次了解学习,所有有任何错误请大家指正。

参考书籍《unix系统高级编程》

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值