引言:

对于C语言程序,了解它执行时在内存中是怎样分配的对于我们理解它的执行机制是很实用的。以下就总结一下C语言程序的一些内存分配知识。

一段C程序。编译连接后形成的可运行文件一般有代码段、数据段、堆和栈等几部分组成。当中数据段又包含仅仅读数据段、已初始化的读写数据段和未初始化的BSS段。例如以下图所看到的:

文本段:存放程序运行的代码。

数据段:

1>仅仅读数据段:

仅仅读数据段是程序使用的一些不会被更改的数据,使用这些数据的方式类似查表式的操作,因为这些变量不须要更改,因此仅仅须要放置在仅仅读存储器中就可以。

通常是const修饰的变量以及程序中使用的文字常量通常会存放在仅仅读数据段中。

2>已初始化的读写数据段:

已初始化数据是在程序中声明,而且具有初值的变量。这些变量须要占用存储器的空间,在程序执行时它们须要位于可读写的内存区域内。而且有初值,以供程序执行时读写。在程序中一般为已经初始化的全局变量,已经初始化的静态局部变量(static修饰的已经初始化的变量)

3>未初始化段(BSS):

未初始化数据是在程序中声明,可是没有初始化的变量,这些变量在程序执行之前不须要占用存储器的空间。

与读写数据段类似,它也属于静态数据区。

可是该段中数据没有经过初始化。

未初始化数据段仅仅有在执行的初始化阶段才会产生,因此它的大小不会影响目标文件的大小。在程序中通常是没有初始化的全局变量和没有初始化的静态局部变量。

堆:需程序猿自己申请(调用malloc,realloc,calloc),并指明大小,并由程序猿进行释放。

栈:由系统自己主动分配。比如,声明在函数中一个局部变量int b;系统自己主动在栈中为b开辟空间。

依据上面的理论知识,分析演示样例片段的内存分配:

栈与堆的差别:

1.申请方式

(1)栈(satck):由系统自己主动分配。比如,声明在函数中一个局部变量int b;系统自己主动在栈中为b开辟空间。

(2)堆(heap):需程序猿自己申请(调用malloc,realloc,calloc),并指明大小,并由程序猿进行释放。

easy产生memory leak.

eg:char  p;

p = (char *)malloc(sizeof(char));

可是,p本身是在栈中。

2.申请大小的限制

(1)栈:栈是向底地址扩展的数据结构,是一块连续的内存区域(它的生长方向与内存的生长方向相反)。栈的大小是固定的。假设申请的空间超过栈的剩余空间时,将提示overflow。

(2)堆:堆是高地址扩展的数据结构(它的生长方向与内存的生长方向同样)。是不连续的内存区域。这是因为系统使用链表来存储空暇内存地址的。自然是不连续的,而链表的遍历方向是由底地址向高地址。

堆的大小受限于计算机系统中有效的虚拟内存。

3.系统响应:

(1)栈:仅仅要栈的空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

(2)堆:首先应该知道操作系统有一个记录空暇内存地址的链表,但系统收到程序的申请时,会遍历该链表。寻找第一个空间大于所申请空间的堆结点。然后将该结点从空暇链表中删除。并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小。这样。代码中的free语句才干正确的释放本内存空间。另外。找到的堆结点的大小不一定正好等于申请的大小,系统会自己主动的将多余的那部分又一次放入空暇链表中。

说明:对于堆来讲,频繁的malloc/free势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率减少。对于栈来讲。则不会存在这个问题,

4.申请效率

(1)栈由系统自己主动分配,速度快。但程序猿是无法控制的

(2)堆是由malloc分配的内存,一般速度比較慢,并且easy产生碎片。只是用起来最方便。

5.堆和栈中的存储内容

(1)栈:在函数调用时,第一个进栈的主函数中后的下一条语句的地址。然后是函数的各个參数,參数是从右往左入栈的,然后是函数中的局部变量。注:静态变量是不入栈的。

当本次函数调用结束后。局部变量先出栈。然后是參数,最后栈顶指针指向最開始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

(2)堆:通常是在堆的头部用一个字节存放堆的大小。

6.存取效率

(1)堆:char *s1=”hellow tigerjibo”;是在编译是就确定的

(2)栈:char s1[]=”hellow tigerjibo”;是在执行时赋值的;用数组比用指针速度更快一些,指针在底层汇编中须要用edx寄存器中转一下,而数组在栈上读取。

补充:

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令运行。这就决定了栈的效率比較高。

堆则是C/C++函数库提供的,它的机制是非常复杂的,比如为了分配一块内存。库函数会依照一定的算法(详细的算法能够參考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,假设没有足够大小的空间(可能是因为内存碎片太多)。就有可能调用系统功能去添加程序数据段的内存空间。这样就有机会分到足够大小的内存,然后进行返回。显然。堆的效率比栈要低得多。

7.分配方式:

(1)堆都是动态分配的,没有静态分配的堆。

(2)栈有两种分配方式:静态分配和动态分配。静态分配是编译器完毕的。比方局部变量的分配。

动态分配由alloca函数进行分配,可是栈的动态分配和堆是不同的。

它的动态分配是由编译器进行释放,无需手工实现。

參考1:http://blog.csdn.net/tigerjibo/article/details/7423728

參考2:http://blog.csdn.net/to_be_it_1/article/details/31420549

參考3:http://blog.csdn.net/lovecodeless/article/details/24384093

參考4:http://blog.csdn.net/lovecodeless/article/details/21084513

转载于:https://www.cnblogs.com/yxwkf/p/5115601.html

【C语言天天练(二四)】内存分配相关推荐

  1. 计算机二级换c语言,09年计算机二级C语言辅导:C技巧(内存分配:更换策略,不要为难内存)...

    09年计算机二级C语言辅导:C技巧(内存分配:更换策略,不要为难内存) 分类:计算机等级| 更新时间:2008-11-21| 来源:教育联展网 在32位机上(64位也是一样的,但是空间大很多),一个进 ...

  2. linux c语言 glibc 错误 munmap,Linux内存分配小结--malloc、brk、mmap

    Linux的虚拟内存管理有几个关键概念: 1.每个进程都有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址: 2.虚拟地址可通过每个进程上的页表(在每个进程的内核虚拟空间地址)与物理地址进行 ...

  3. java 内存分配实例_java学习(四) —— 内存分配浅析

    前言 java中有很多类型的变量.静态变量.全局变量及对象等,这些变量在java运行的时候到底是如何分配内存的呢?接下来有必要对此进行一些探究. 基本知识概念: (1)寄存器:最快的存储区, 由编译器 ...

  4. 【C语言】为什么存在动态内存分配

    文章目录 前言 一.动态内存分配 定义 二.动态内存分配的意义 1.可以控制所开辟的内存大小 2.可以多次利用这部分空间 三,动态内存函数的介绍 前言 提示:我们先来看一个在vs编译器下,同学们常犯的 ...

  5. C语言在STM32中的内存分配

    01.前言 不说废话,先上示例代码 uint8_t num_byte[4]; uint32_t num_word; const uint32_t num_word_const = 0x1234; ui ...

  6. C语言学习笔记之动态内存分配结构体——辣鸡版学生管理系统

    @[C语言学习笔记] 小辣鸡自学C语言中,好多视频教程都有这个案例,小辣鸡自己边学边记,下边是代码. 如有错误,感谢告知!!! #include<stdio.h> #include< ...

  7. 【C语言天天练(十九)】restrict关键词

    引言:在内核的系统调用函数里,常常遇到函数的參数使用restrict限定词限定的情况,以下就对该关键词做个总结. 1.restrict关键词是C99特性才加入的,因此在编译使用含有该限定词的程序时,一 ...

  8. 【C语言进阶学习笔记】五、动态内存分配(爆肝吐血力作,强烈建议收藏!!!)

    前言 现代计算机基本都是基于冯诺伊曼结构体系设计出来的,冯诺伊曼结构体系的核心就是"存储程序",将程序(指令集)和数据以同等地位存储在内存中.但是我们的内存空间并不是无限大的,所以 ...

  9. C语言第十三课,动态内存分配

    动态内存分配的空间放在堆区.动态内存函数主要有:malloc,calloc,realloc 动态内存函数的介绍 malloc 申请一个空间,大小是size的大小,指向的一个类型不明,因为在设计的时候, ...

最新文章

  1. JDBC编程:1(使用JDBC连接数据库)
  2. 江翰服务器保护系统(JH-Data Backup server)
  3. 过于自嗨的《紫塞秋风》,怎么就成了行业教科书?
  4. Express接口综合案例(创建项目、配置常用中间件、路由设计、提取控制器模块、配置错误统一处理中间件、用户注册的数据验证,密码加密)
  5. 为什么java中floatda正确_为什么cast to float在java中产生正确的结果?
  6. Flask Jinja2 模板中的变量和过滤器
  7. matlab第二版实验七,matlab实验七.doc
  8. java通讯录工程_JAVA通讯录管理小项目
  9. Hadoop报错:could only be replicated to 0 nodes, instead of 1
  10. DBParameter比拼接字符串慢的解决办法
  11. 五步构建经营指标,拒绝分析不接地气
  12. 2019/第十届蓝桥杯国赛/Java-B
  13. css实现加载旋转动画
  14. linux安装vsftpd
  15. 如何把UCos-ii_在STM32上的移植
  16. (日常)Dell R740 XD 服务器安装GPU显卡记录
  17. vue倒计时:天时分秒
  18. java输入成绩并排序简单_java 成绩排序
  19. HC32F460开发之硬件IIC驱动AT24C64
  20. 【Linux命令】ip addr、ip link、ifconfig 用法 二

热门文章

  1. c语言除法效率问题,【图片】今天写几个性能测试,为什么C语言跑得这么慢呢??【c语言吧】_百度贴吧...
  2. 2导出指定表结构_大白话详解大数据hive知识点,老刘真的很用心(2)
  3. ubuntu 开启ssh_CS学习笔记 | 22、通过SSH开通通道
  4. UE4学习-在虚幻编辑器中打开VS的三种方式
  5. UE4学习-创建基于C++的场景
  6. 与华为交换机用access_学校机房项目交换机的配置,理解这篇,交换机配置不再难...
  7. python敏感字替换_教学案例_Python处理敏感词汇方法
  8. python编程竞赛规则_用python实行羽毛球比赛规则。
  9. sql中当前日期加2个月_一文搞定Mysql日期时间函数
  10. 常用的分隔符有哪三种_三种废水处理方法