【C&C++】C程序内存布局

对于C语言的学习、掌握,内存的理解是一定绕不开的,本文主要是基于实际的小例子来简单讲解下C程序的内存分布

通常一个C程序主要由以下几个部分构成,

  1. 代码段(Text segment or Code segment)
  2. 已初始化数据段(Initialized data segment )
  3. 未初始化数据段也常称为"bss"段(Uninitialized data segment )
  4. 栈(Stack)
  5. 堆(Heap)

内存分布

一探究竟
名词解释
  • 代码段( Code segment )
    代码段主要存储的是可执行程序的代码指令,从内存区域划分看,代码通常可以放在堆栈的下方,防止堆栈溢出导致代码段被覆盖.

    另外通常代码段是只读的,防止可执行程序对程序的指令造成修改.

  • 已初始化数据段(Data Segment)
    已初始化话数据段,通常简称为数据段. 包含了已经由程序员完成初始化的全局变量、静态变量.

    数据段可以进一步划分为,只读和可读可写两个区域.
    例如,在C代码中,int test = 1; 定义在mian函数外(全局变量),就存放在可读可写区域.
    然后定义的全局char指针变量, char *str = “Hello”, "Hello"就是被存储在只读区域.

  • 未初始化数据段(Uninitialized data segment )
    未初始化数据段,也被称为"bss - block started by symbol"段.
    与数据段相对,不是由程序员进行全局变量 or 静态变量的初始化,而是在程序开始执行时由系统初始化为0.

  • Stack
    栈区域通常和堆区是相邻的并且是往相对的方向生长,通常当栈指针生长到和堆指针相等代表空闲内存耗完. Stack 是后进先出的数据结构
    局部变量存放在Stack,函数调用也依托于Stack(函数的形参就是通过Stack进行传递)

*Heap
堆是动态分配的内存区域, 通常开始bss段结束的位置,然后向上生长. 堆区域是由malloc、reallo和free进行管理的, 也就是说malloc、realloc申请的内存是在堆区域.

示例演示

通过Linux下的size指令来解释说明,代码段、数据段、bss段的构成.

示例一,


#include <stdio.h>
 
int main(void)
{
    return 0;
}
test gcc -o memory-layout memory-layout.c
➜  test size memory-layout
   text	   data	    bss	    dec	    hex	filename
   1415	    544	      8	   1967	    7af	memory-layout

数据段大小为: 544
bss段数据大小为: 8

示例二,


#include <stdio.h>
 
int g_v; /* 未初始化的全局变量存储在 bss*/
int g_l;
int main(void)
{
    return 0;
}
test gcc -o memory-layout memory-layout.c
➜  test size memory-layout                  
   text	   data	    bss	    dec	    hex	filename
   1415	    544	     16	   1975	    7b7	memory-layout

如上所示,在增加未初始化的全局变量后,bss段变大,text、data未有任何变化.

示例三,

#include <stdio.h>
 
int g_v; /* 未初始化的全局变量存储在 bss*/
int g_l;
int main(void)
{
    static int i; /* 未初始化的静态变量 存储在 bss */
    static int j; /* 未初始化的静态变量 存储在 bss */
    return 0;
}

➜ test gcc -o memory-layout memory-layout.c
➜ test size memory-layout
text data bss dec hex filename
1415 544 24 1983 7bf memory-layout

如上所示,在增加未初始化静态变量的定义后,bss段再一次变大

示例四,



#include <stdio.h>
 
int g_v; /* 未初始化的全局变量存储在 bss*/
int g_l; 
int main(void)
{
    static int i = 100; /* 始化的静态变量 存储在 数据段 */
    static int j = 100; /* 始化的静态变量 存储在 数据段*/
    return 0;
}

➜ test gcc -o memory-layout memory-layout.c
➜ test size memory-layout
text data bss dec hex filename
1415 552 16 1983 7bf memory-layout

如上所示,基于示例三进行静态变量的初始化后,data段变大,而bss段变小.

示例五,

#include <stdio.h>
 
int g_v = 10; /* 初始化的全局变量存储在 数据段*/
int g_l = 10; 
int main(void)
{
    static int i = 100; /* Initialized static variable stored in DS*/
    static int j = 100return 0;
}
test gcc -o memory-layout memory-layout.c
➜  test size memory-layout                  
   text	   data	    bss	    dec	    hex	filename
   1415	    560	      8	   1983	    7bf	memory-layout

如上所示,基于示例四,进行全局变量的初始化后,data段进一步变大,而bss段进一步变小.

示例六,

#include <stdio.h>
 
int g_v = 10; /* 初始化的全局变量存储在 数据段*/
int g_l = 10; 
int main(void)
{
    static int i = 100; /* Initialized static variable stored in DS*/
    static int j = 100if(i == 100)
    	printf("Hello \r\n");
    return 0;
}
test gcc -o memory-layout memory-layout.c
➜  test size memory-layout                  
   text	   data	    bss	    dec	    hex	filename
   1526	    616	      8	   2150	    866	memory-layout

如上所示,在基于示例五,增加if等指令后,text段变大.

总结

无论是学习C语言还是C++,对于程序内存分布的理解是非常重要的一环节,对于嵌入式开发中一定要理解C程序的内存分布情况.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值