linux-C语言内存管理精讲

 1. linux-C进程内存布局

   任何一个程序,正常运行都需要内存资源,用来存放诸如变量、常量、函数代码等等。这些不同的内容,所存储的内存区域是不同的,且不同的区域有不同的特性。因此我们需要研究内存布局,逐个了解不同内存区域的特性。
   每个C语言进程都拥有一片结构相同的虚拟内存,例如三个完全不相干的进程p1、p2、p3,它们很显然会占据不同区段的物理内存,但经过系统的变换和映射,它们的虚拟内存的布局是完全一样的。
PM:Physical Memory,物理内存。
VM:Virtual Memory,虚拟内存。

将其中一个C语言进程的虚拟内存放大来看,会发现其内部包下区域:
1.栈(stack)
2.堆(heap)
3.数据段
4.代码段

    虚拟内存中,内核区段对于应用程序而言是禁闭的,它们用于存放操作系统的关键性代码,另外由于 Linux 系统的历史性原因,在虚拟内存的最底端 0x0 ~ 0x08048000 之间也有一段禁闭的区段,该区段也是不可访问的。


2. 栈内存

  1.栈,又称堆栈,是现代计算机程序极为重要的组成部分,几乎所有的函数调用都依赖于栈进行实现。栈维护了一个函数调用过程中所需要的信息,被称为栈帧。栈帧中一般维护了以下几类重要的数据举例:

o  函数返回地址:记录了函数执行完成后,退出函数调用时需要执行的下一条指令
o 函数参数:在调用子函数时,程序将函数参数依序保存在栈上
o 局部变量:函数调用过程中使用的非静态局部变量均默认保存在栈上,函数退出后,这些变量也会被释放而不可使用
o  保存的寄存器(环境变量等):保存了函数调用前后需要保持不变的寄存器

2.在程序运行过程中,每次执行函数调用,都会建立一个栈帧,连续的过程调用会让栈不断朝着“栈顶”的方向进行扩展;在函数调用完成后,栈帧会被自动释放,栈也会随之缩减。在大多数体系结构上,栈的扩展方向都是由高地址向低地址进行扩展。
3.栈内存有什么特点?
空间有限,尤其在嵌入式环境下。因此不可以用来存储尺寸太大的变量。
每当一个函数被调用,栈就会向下增长一段,用以存储该函数的局部变量。
每当一个函数退出,栈就会向上缩减一段,将该函数的局部变量所占内存归还给系统。
栈内存的分配和释放,都是由系统规定的,我们无法干预。

举例

3.数据段和代码段

数据段细分成如下几个区域:
o  .bss 段(Block Started by Symbol):未初始化的全局变量和静态局部变量保存在bss段,它们将被系统自动初始化为0。
o   .data段(data segment):数据段。保存已经初始化的全局变量和静态局部变量。
o   .rodata段:只读数据段。存放的是只读数据,一般是程序里面的只读变量(const修饰的变量)、字符串变量、常量数据(printf 的格式化字符也算)。

4.局部变量

  1. 在函数内部定义的变量是局部变量,其有效范围是局限于函数内部的,形参也是局部变量。
  • 正是因为局部变量的有效使用范围的局限,可以最大程度的确保各函数之间的独立性,避免函数之间相互干扰。

    5.全局变量

  • 定义在函数外的变量,不属于任何函数。其作用范围是从定义开始到程序结束,对作用范围内所有的函数都起作用
  • 全部变量的定义格式与局部变量完全一致,只是定义的位置不在函数内,它可以定义在函数的头部,也可以定义在两个函数的中间或程序尾部,只要在函数外部即可。
  • 当某函数的局部变量与全局变量同名时,那么全局变量在该函数中不起作用,局部变量起作用。若不存在同名变量的函数,那么全局变量仍然起作用。

    6.静态变量

     1.静态局部变量

  • 在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。
  • 内存中的位置:静态存储区(使得局部变量由原来存储在栈内存,变成存储在静态存储区。)
  • 初始化:未经初始化的局部静态变量会被程序自动初始化为0
  • 作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

生存周期:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束。


2.全局静态变量

1.在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。

  • 内存中的位置:静态存储区
  • 初始化:未经初始化的全局静态变量会被程序自动初始化为0
  • 作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。

2.定义全局静态变量的好处:

  • 不会被其他文件所访问,修改
  • 其他文件中可以使用相同名字的变量,不会发生冲突。

7.堆内存

  • 堆内存(heap)又被称为动态内存、自由内存,简称堆。堆是唯一可被开发者自定义的区段,开发者可以根据需要申请内存的大小、决定使用的时间长短等。但又由于这是一块系统“飞地”,所有的细节均由开发者自己把握,系统不对此做任何干预,给予开发者绝对的“自由”,但也正因如此,对开发者的内存管理提出了很高的要求。对堆内存的合理使用,几乎是软件开发中的一个永恒的话题。

  • 堆内存基本特征:

  • 相比栈内存,堆的总大小仅受限于物理内存,在物理内存允许的范围内,系统对堆内存的申请不做限制。

  • 相比栈内存,堆内存从下往上增长。

  • 堆内存是匿名的,只能由指针来访问。

  • 自定义分配的堆内存,除非开发者主动释放,否则永不释放,直到程序退出。
  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值