C语言内存分配
2015-09-02 10:30
302 查看
网上看到一 篇讲得不错的关于内存分配的文章,对其中的知识进行了归纳整理和验证,也算是解决了困惑已久的疑惑了,如有理解不当之处,希望多多指正。
原文:http://blog.csdn.net/youoran/article/details/10990815#comments
yuanhui@C179:~/c$ sizea.out
text data bss dec hex filename
1448 576 8 2032 7f0 a.out
代码区静态数据/全局初始化数据区 未初始化数据区 十进制总和 十六进制总和 文件名
1、 代码区的指令包括操作码和需要操作的对象,该区域的数据一般是只读的,
2、 数据区是一些初始化的全局变量、静态变量、常量
3、 未初始化数据区(bbs)是一些未初始化的全局变量,该区域的值在函数程序执行之前被赋值为0或者是空指针,在运行时改变其值。
当程序运行的时候对应的就产生了堆区和栈区。
栈区:由编译器自动分配释放,存放函数的参数值、局部变量的值等
堆区:用于动态内存分配。堆在内存中位于bss区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时有可能由OS回收
下面的例子讲述了数据的内存上的布局
1、静态分配是在程序执行之前就分配了的,所以相对而言,他的效率是比较高的
2、静态分配是有名字的变量,而动态分配则需要使用指针间接地对它进行操作。
Int a= 100:编译器分配存储区来存放这个整数,该存储区和名称a相互对应,并用100初始化这个存储区
p=(int*)malloc(sizeof(int))在堆区分配4个字节的存储区,返回该存储区的地址,并初始化给指向整形类型的指针p,如果需要访问存储区的数据,需要通过访问他的地址来访问这个对象
3、静态对象的分配和释放由编译器自动完成,动态对象的分配和释放必须由程序员自己管理。
栈是直接由编译器管理的,堆是由程序员自己管理的
2、空间大小不同
栈是向低地址扩展的数据结构,栈顶地址和栈的大小是预先设定好的,而且他的地址空间是连续的,所以容量一般较小
堆是向高地址扩展的数据结构,他的地址不是连续的,因为只要是高地址上有剩余的空间他就可以不停的开始动态分配,来使用一些相对来说比较零散的地址空间,为什么我们在使用指针的时候一定会遇到链表这个东西呢!因为堆上的空闲的内存地址就是使用链表来存储的。这样堆的数据也比较大。
3、存储数据
栈:函数的参数、需要多次调用的代码(递归)、局部变量
堆:动态分配的地址
4、是否产生碎片
对于堆来说,频繁的malloc和free一定会产生磁盘空间不连续,从而产生很多的碎片,程序在退出的时候(会对磁盘空间进行回收管理)但是太多的磁盘碎片会使得程序效率降低。
5、增长方向不同
堆上的地址是向上增长的,栈上的地址是向下增长的。
6、分配方式不同
堆上空间是动态分配,栈上的空间是静态分配
7、分配效率
栈的分配效率高于堆:栈是由编译器直接管理的,计算机底层会直接对栈提供支持,堆
则需要调用库函数,他的分配机制很复杂,库函数会按照一定的算法在地址空间是搜索可用的足够大的空间,如果没有足够大的可用操作空间,就需要操作系统来重新整理内容空间,然后再开始分配
所有的内存分配函数,都是在堆上分配一个连续的空间,产生碎片化是指整个堆上的磁盘文件会产生碎片,但是内存分配函数分配的空间是一个连续的空间。
所以会存在分配内存空间失败的情况,这个时候,我们就需要对分配完成的内存空间做相应的判断。
原文:http://blog.csdn.net/youoran/article/details/10990815#comments
内存布局
在认识内存分配之前,我们需要先了解一个可执行程序在运行前内存上对应的数据分区yuanhui@C179:~/c$ sizea.out
text data bss dec hex filename
1448 576 8 2032 7f0 a.out
代码区静态数据/全局初始化数据区 未初始化数据区 十进制总和 十六进制总和 文件名
1、 代码区的指令包括操作码和需要操作的对象,该区域的数据一般是只读的,
2、 数据区是一些初始化的全局变量、静态变量、常量
3、 未初始化数据区(bbs)是一些未初始化的全局变量,该区域的值在函数程序执行之前被赋值为0或者是空指针,在运行时改变其值。
当程序运行的时候对应的就产生了堆区和栈区。
栈区:由编译器自动分配释放,存放函数的参数值、局部变量的值等
堆区:用于动态内存分配。堆在内存中位于bss区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时有可能由OS回收
下面的例子讲述了数据的内存上的布局
内存分配
静态分配和动态分配,1、静态分配是在程序执行之前就分配了的,所以相对而言,他的效率是比较高的
2、静态分配是有名字的变量,而动态分配则需要使用指针间接地对它进行操作。
Int a= 100:编译器分配存储区来存放这个整数,该存储区和名称a相互对应,并用100初始化这个存储区
p=(int*)malloc(sizeof(int))在堆区分配4个字节的存储区,返回该存储区的地址,并初始化给指向整形类型的指针p,如果需要访问存储区的数据,需要通过访问他的地址来访问这个对象
3、静态对象的分配和释放由编译器自动完成,动态对象的分配和释放必须由程序员自己管理。
堆和栈的区别
1、管理方式栈是直接由编译器管理的,堆是由程序员自己管理的
2、空间大小不同
栈是向低地址扩展的数据结构,栈顶地址和栈的大小是预先设定好的,而且他的地址空间是连续的,所以容量一般较小
堆是向高地址扩展的数据结构,他的地址不是连续的,因为只要是高地址上有剩余的空间他就可以不停的开始动态分配,来使用一些相对来说比较零散的地址空间,为什么我们在使用指针的时候一定会遇到链表这个东西呢!因为堆上的空闲的内存地址就是使用链表来存储的。这样堆的数据也比较大。
3、存储数据
栈:函数的参数、需要多次调用的代码(递归)、局部变量
堆:动态分配的地址
4、是否产生碎片
对于堆来说,频繁的malloc和free一定会产生磁盘空间不连续,从而产生很多的碎片,程序在退出的时候(会对磁盘空间进行回收管理)但是太多的磁盘碎片会使得程序效率降低。
5、增长方向不同
堆上的地址是向上增长的,栈上的地址是向下增长的。
6、分配方式不同
堆上空间是动态分配,栈上的空间是静态分配
7、分配效率
栈的分配效率高于堆:栈是由编译器直接管理的,计算机底层会直接对栈提供支持,堆
则需要调用库函数,他的分配机制很复杂,库函数会按照一定的算法在地址空间是搜索可用的足够大的空间,如果没有足够大的可用操作空间,就需要操作系统来重新整理内容空间,然后再开始分配
C内存分配函数
在栈上分配内存的函数是calloc,实际上还有一个对malloc进行简化和优化的函数叫alloca函数,这个函数对分配的内存空间再进行了一次初始化设置对他的空间进行初始化,这也是以前敲代码的时候没有注意到的地方,malloc函数是没有自带初始化的功能的,所以我们需要使用memset进行初始化所有的内存分配函数,都是在堆上分配一个连续的空间,产生碎片化是指整个堆上的磁盘文件会产生碎片,但是内存分配函数分配的空间是一个连续的空间。
所以会存在分配内存空间失败的情况,这个时候,我们就需要对分配完成的内存空间做相应的判断。
相关文章推荐
- C语言中改变目录的相关操作函数详解
- 【内存泄露/C++】基于重载new运算符的内存泄露检测工具
- C++函数返回多个参数
- C++中的inline函数
- C++基础
- c++ 扩栈
- Effective C++ 改善程序与设计的55个具体做法 读书笔记
- C++中 模板Template的使用
- std空间和全局命名空间
- 详解C语言中symlink()函数和readlink()函数的使用
- C++函数指针
- C语言复习 -- 结构体指针与自增运算符
- 简单谈谈C++ 中指针与引用
- C语言中的结构体与C++中的类异同
- CALLBACK--_stdcall(PASCAL调用方式),VS默认是C语言调用方式即__cdecl
- C/C++中static关键字不同的含义详解
- C语言的实用工具库
- C++ Primer : 第十三章 : 拷贝控制之拷贝、赋值与销毁
- 开始使用虚幻4并创建一个简单的c++类
- C语言编写控制台下PE分析工具(四)