C程序内存布局

        我们知道,早期的计算机系统都是冯·诺依曼体系结构,它是一种将指令和数据合并在一起存储的系统结构。这样CPU在执行程序的时候,将会从指令寄存器(IR,Instruct Register)中取指令并译码执行,而从数据寄存器(DR,Data Register)中取所要操作的数据。因此,对于系统而言就需要区分程序中哪些部分是指令,哪些部分又是数据。

        事实上,C程序在编译生成可执行程序a.out的时候,链接器会将所有的代码放到代码段,而将数据放到数据段中。这样当C程序在运行时,操作系统会按照下面的内存分布图为该进程分配相应的内存空间,并初始化每个段(Segmentation)的数据。

        另外需要注意的是,不同的段具有不同的使用特性。譬如有些段的内存空间是只读的(如代码段、RoData段),这样当我们在代码中尝试修改这些内存空间时,操作系统就会给我们的进程发送SIGSEGV信号,这时我们运行的程序就会立刻退出并打印“Segmentation fault(段错误)”。

                                      7d94dcbf07824549ba54e90dd3e01a50.jpeg

代码段(code segment/text segment):

代码段也叫文本段,它在程序运行期间一直存在。该段主要是用来存放程序中的二进制指令,也就是我们C程序中的执行代码。如函数中的var++中的自加运算就是代码,它就存放在代码段中。很显然这个段具有只读的属性,任何对它的修改都会导致“Segmentation fault”。

数据段(data segment):

数据段顾名思义就是用来存放数据的,它在程序运行期间一直存在。该段又分为三个部分:rodata区、data区和bss区。 

rodata(readonly data)区:是只读数据区,#define MSG "hello" 或char *str="hello"中的"hello"常量就存放在这里。该段内存空间具有只读的属性,任何对它的修改都会导致“Segmentation fault”。该段内存空间的数据为其初始化的相应值。

data区:用来存放初始化为非零的全局变量或静态(static关键字修饰)变量。该段内存空间的数据为其初始化的相应值

bss(block started by symbol)区:用来存放未初始化或初始化为零的全局变量或静态(static关键字修饰)变量。该段内存空间内所有的数据默认为0.

堆栈区(Stack Heap):

这里所说的堆栈并不是指数据结构中的存储结构堆栈(Stack,先进后出),而是指C程序布局中的堆区(Heap)和栈区(Stack)。这段内存空间中的数据均为随机值,并且它们只有在程序运行时才存在。

栈区:存放的是没有用static关键字修饰的局部变量,它在“{”内定义的位置开始生效,到“}”结束时失效,并且由系统自动管理,再次进入到“{}”内时将重新分配内存空间;

堆区:是由程序员手动管理的一块内存,它的申请malloc()和释放free()必须由程序员自己调用函数实现,如果程序员在使用完该片内存后并没有释放,将会导致内存泄漏(memory leak).

命令行参数区:

我们知道 C 程序的 main() 函数可以传入参数,而这些参数正是命令行在执行该程序时传入的命令行参数。那main()函数中的参数就存放在命令行参数区

系统空间:

这是操作系统在运行C程序时保存的一段内存空间,如共享内存(shared memory) 就是使用的这段地址空间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

弗朗克21

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

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

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

打赏作者

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

抵扣说明:

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

余额充值