【C语言天天练(二四)】内存分配
引言:
对于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
【C语言天天练(二四)】内存分配的更多相关文章
- JVM学习总结四——内存分配策略
之前几篇我们介绍了jvm的内存模型以及垃圾回收机制,而本篇我们将介绍几个JVM中对象在分配内存是应该遵循的策略.毕竟,想要去优化程序,不仅要考虑垃圾回收的过程,还要从对象内存分配的角度减少gc的代价. ...
- 【C语言天天练(九)】动态内存分配
引言:数组的元素存储于内存中连续的位置上.当一个数组被声明时.它所须要的内存在编译时就被分配. 可是,我们能够使用动态内存分配在执行时为它分配内存. 一块内存的生命周期能够分为四个阶段:分配.初始化. ...
- 你必须了解的java内存管理机制(二)-内存分配
前言 在上一篇文章中,我们花了较大的篇幅去介绍了JVM的运行时数据区,并且重点介绍了栈区的结构及作用,相关内容请猛戳!在本文中,我们将主要介绍对象的创建过程及在堆中的分配方式. 相关链接(注:文章讲解 ...
- [C语言] 数据结构-预备知识动态内存分配
动态内存分配 静态内存分配数组 int a[5]={1,2,3,4,5} 动态内存分配数组 int len=5; int *parr=(int *)malloc(sizeof(int) * len) ...
- 【C语言天天练(二一)】内联函数
引言:调用函数时,一般会由于建立调用.传递參数.跳转到函数代码并返回等花费掉一些时间,C语言的解决的方法是使用类函数宏.在C99中,还提出了第二种方法:内联函数. 内联 ...
- 【C语言天天练(二)】预处理
引言: 学C语言之初.一提到预处理,脑子里想到的就是#define的宏定义以及#include包括的头文件.后来随着对C的深入学习发现.预处理不止这些.比方条件编译.提前定义的宏等等.以下对此进行总结 ...
- 【C语言天天练(二)】statickeyword
引言: statickeyword不仅能够修饰变量.并且能够修饰函数.了解它的使用方法,不仅对阅读别人的代码有帮助,也有助于自己写出更加健壮的程序. 使用方法: ...
- 【C语言天天练(二二)】位操作
C的位运算符 1.二进制反码或按位取反:~ ~(10011010) = (01100101). 假设val是一个unsigned char,~val不改名原来val的值. 2.位与:& 二进制 ...
- 【C语言天天练(十五)】字符串输入函数fgets、gets和scanf
引言:假设想把一个字符串读到程序中.必须首先预留存储字符串的空间.然后使用输入函数来获取这个字符串. 读取字符串输入的第一件事是建立一个空间以存放读入的字符串. char *name; scanf(& ...
随机推荐
- cloudflare的新waf,用Lua实现的
我们使用nginx贯穿了我们的网络,做前线web服务,代理,流量过滤.在某些情况下,我们已经扩充了nginx上我们自己的模块的核心C代码,但近期我们做了一个重大举措,与nginx结合使用lua 差点儿 ...
- Swift - 获取字符串的MD5值
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译摘要算法.哈希算法),主流编程语言普遍已有MD5实现. ...
- Google C++ style guide——命名约定
1.通过命名规则 函数命名.变量命名.文件命名应具有描写叙述性. 类型和变量应该是名词,函数名能够用"命令性"动词. 2.文件命名 文件名称所有小写,能够包括下划线(_)或者断线( ...
- C语言,题目:函数调用,内存,malloc找错
malloc int* p = (int *) malloc (sizeof(int)*128); //分配128个(可根据实际需要替换该数值)整型存储单元,并将这128个连续的整型存储单元的首地址存 ...
- EFM32在使用IAR开发环境配置ICf文件以及指定程序存储地址空间
EFM32在IAR开发环境下指定代码,数据的存储空间 为了便于后续的项目升级,管理,需要对代码,数据的存储空间加以设定,也在网上找下相关的资料,笔者水平有限, 如下内容不一定完全正确,如有错误之后,还 ...
- [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传
原文 [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传 Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件 ...
- linux命令:du,看文件大小
du -s698 . (698字节)From <http://jingyan.baidu.com/article/a17d52855c10bf8098c8f2c9.html>
- JS - 焦点图
下载地址:http://www.lanrentuku.com/js/jiaodiantu-1076.html 修改焦点图: CSS代码: /* 懒人图库 搜集整理 www.lanrentuku.com ...
- 【ASP.NET Web API教程】2 创建各种Web API
原文 [ASP.NET Web API教程]2 创建各种Web API Chapter 2: Creating Web APIs第2章 创建各种Web API 本文引自:http://www.asp. ...
- c语言指针具体解释
指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最基本的风格之中的一个.利用指针变量能够表示各种数据结构: 能非常方便地使用数组和字符串: 并能象汇编语言一样处理内存地址,从而编出精练而高 ...