glibc 内存申请和释放及堆连续检查
C语言有两种内存申请方式:
1、静态申请:当你声明全局或静态变量的时候,会用到静态申请内存。静态申请的内存有固定的空间大小。空间只在程序开始的时候申请一次,并且不再释放(除非程序结束)。
2、自动申请:当你声明自动变量的时候会使用自动申请。函数参数、局部变量都属于自动变量。这些变量空间在程序执行致相关语句块申请,离开语句块时释放。
还有一种内存申请方式:动态内存申请。C语言变量并不支持动态内存申请,这一功能由库函数实现。C里面没有动态这个存储类型!!
当你需要存储一些数据,但又不知道这些数据有多大或者这些数据会不断的增加。这是后使用动态申请内存技术会非常有用。动态申请是一种显示申请行为,你必须调用相关函数或者宏,并指名申请的大小。申请到的内存空间只能使用指针访问,动态内存还会消耗额外的计算时间,使用起来颇为不便。所以除非必须自动申请和静态申请都不管用,才会考虑动态申请。当然啦,动态申请是一项很重要的技术,没了他不行。
malloc函数原型:
void *malloc(size_t size)
说明: malloc函数申请的内存空间并不会初始化。我们需要手动使用memset函数将内存快置零。
内存对齐:malloc申请到的内存在32位系统中以8的倍数对齐,64位系统中以16的倍数对齐。如果想以一整页对齐,则需要aligned_alloc或者posix_memalign函数。
返回值:无法申请内存时,返回空指针。
memset函数原型:
void *memset(void *block, int c, size_t size)
如果你想为字符串申请内存,记得大小为长度+1——字符串的最后的空字符并没有被计入长度。
char *ptr;
...
ptr = (char *) malloc (length+); //强制转换
内存释放函数(用来释放malloc申请的内存):
#include<stdlib.h>
void free(void *ptr); //释放ptr指向的内存块
void cfree(void *ptr); //和free一样,但提供与SunOS的兼容性。推荐使用free
如果你想调整动态申请的内存的大小,使用realloc函数,原型如下:
#include<stdlib.h>
void *realloc(void *ptr, size_t newsize)
/*如果旧的内存块后面没有足够的空间申请额外的内存,realloc会重新找一块
*地方申请newsize大小的内存,并将旧内存复制到新内存中。
*返回值:无法申请空间时返回空指针,原内存空间无变化。
*/
申请一块干净的内存空间,我们之前使用malloc,在使用memset清空内存空间。现在我们使用calloc一步到位。
#include <stdlib.h>
void *calloc(size_t count, size_t eltsize)
/*等同于
void * calloc(size_t count, size_t eltsize)
{
size_t size = count * eltsize;
void *value = malloc(size);
if (value != 0) memset(value, 0, size);
return value;
}
*/
malloc的效率问题:
GNU C库中,malloc实际申请的内存大小不会以2的n次方呈现,他会和周围的内存碎片合并,从而避免内存的浪费。
如果需要申请大的内存块(大于一个页),可以使用mmap。mmap函数申请的内存实际上是内存IO映射。我们知道程序面对的是虚拟内存,虚拟内存的背后要有实际物理内存。实际物理内存可以借用辅存。内存是按页划分的,申请大于一个页的内存会有什么事情发生呢?这一页的实际物理内存会被系统锁定。那么很大的物理内存无法被其他程序利用。而我们使用mmap函数,是将虚拟内存和辅存上的文件对应,最重要的是:只有程序对对这块虚拟内存操作的时候,才会申请相应大小实际物理内存。还有个问题是碎片化,如果你申请的内存恰好在两个被使用的内存之间,而你申请的内存有很大,那剩下的空间就很小(可能谁也用不了)(个人理解)
关于内存对齐
malloc 和realloc返回的块地址永远是8的倍数或者64位系统下16的倍数(这和之前所说的大小并不是一回事),如果你想返回更高的倍数可以使用aligned_alloc或者posix_memalign(不过多大的倍数,都必须是2的n次方)
#include<stdlib.h>
void *aligned_alloc(size_t alignment, size_t size)
/*说明*/
//申请size大小的内存块,地址为alignment的倍数(size必须为alignment的倍数)
//如果出错会设置errno,详情请man aligned_alloc
//ISO C11之后的标准支持该函数,在非POSIX系统中兼容性比posix_memalign好
#include <stdlib.h>
void *memalign(size_t boundary, size_t size)
/*说明*/
//memalign同样申请size大小的内存,返回的地址为boundary的倍数。不同的是memalign实际申请的内存大小会稍微大一些(避免内存碎片化),返回的地址实际为内存块里的一个特定边界
#include<stdlib.h>
int posix_memalign(void **memptr, size_t alignment, size_t size)
/*说明*/
//posix_memalign通过memptr返回地址,所以memptr使用了指针的指针。(应该不难理解)
//与memalign不同的地方:alignment的值必须是sizeof(void *)的正数倍,且为2的n次方。(当然所有的内存对齐申请函数的alignment都必须是2的n次方)
#include<stdlib.h>
void *valloc(size_t size) /*说明*/
//等同于如下的函数
void * valloc (size_t size)
{
return memalign(getpagesize(), size);
} //可见,valloc申请的内存边界是以页为大小的。
想要设置内存申请的参数,可以使用mallopt函数
#include <malloc.h>
int mallopt(int param, int value);
传进的参数是一对的,param=value。详细介绍以后再写,或者查看man手册。
动态申请的内存块是堆内存,堆内存不一定是连续的。如果我们想检查其连续性可以使用mcheck函数
#include<mcheck.h>
int mcheck(void (*abortfn) (enum mcheck_status status))
/*简要说明*/
//参数:函数指针,该函数指针指向的函数需要接收mcheck_status的枚举类型。
//mcheck 在检查堆连续性时,如果发现不连续,会调用abortfn指向的函数。如果你提供的时空指针,则会使用默认函数(打印相关信息后停止程序)
//为了能让mcheck函数起作用,你需要在编译选项中添加-lmcheck选项。
//另外你也可以在gdb调试时调用mcheck函数。
//状态值:描述了不连续的类型(具体的查看手册)
glibc 内存申请和释放及堆连续检查的更多相关文章
- Unity内存申请和释放
转自:http://www.jianshu.com/p/b37ee8cea04c 1.资源类型 GameObject, Transform, Mesh, Texture, Material, Shad ...
- C语言学习之我见-malloc和free内存申请及释放函数
malloc函数负责向计算机申请确定大小的内存空间. free函数负责释放malloc的申请空间. (1)函数原型 void free(void *_Memory); void * malloc(si ...
- C语言动态内存的申请和释放
什么是动态内存的申请和释放? 当程序运行到需要一个动态分配的变量时,必须向系统申请取得堆中的一块所需大小的存储空间,用于存储该变量.当不再使用该变量时,也就是它的生命结束时,要显式释放它所占用的存储空 ...
- [CareerCup] 13.9 Aligned Malloc and Free Function 写一对申请和释放内存函数
13.9 Write an aligned malloc and free function that supports allocating memory such that the memory ...
- Win3内存管理之私有内存跟共享内存的申请与释放
Win3内存管理之私有内存跟共享内存的申请与释放 一丶内存简介私有内存申请 通过上一篇文章.我们理解了虚拟内存与物理内存的区别. 那么我们有API事专门申请虚拟内存与物理内存的. 有私有内存跟共享内存 ...
- C++函数中,两个自动释放内存的动态内存申请类
最近做一个事情,实现一个流程交互,其中主交互流程函数中,涉及较多的内存申请, 而健康的函数,都是在函数退出前将手动申请不再需要的内存释放掉, 使用很多方法,都避免不了较多的出错分支时,一堆的if fr ...
- 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现
http://blog.csdn.net/pi9nc/article/details/23334659 注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料 ...
- glibc内存管理那些事儿
本文转载自glibc内存管理那些事儿 Linux内存空间简介 32位Linux平台下进程虚拟地址空间分布如下图: 进程虚拟地址空间分布 图中,0xC0000000开始的最高1G空间是内核地址空间,剩下 ...
- 2万字|30张图带你领略glibc内存管理精髓(因为OOM导致了上千万损失)
前言 大家好,我是雨乐. 5年前,在上家公司的时候,因为进程OOM造成了上千万的损失,当时用了一个月的时间来分析glibc源码,最终将问题彻底解决. 最近在逛知乎的时候,发现不少人有对malloc/f ...
随机推荐
- Berkeley DB基础教程 分类: H3_NUTCH 2014-05-29 15:21 2212人阅读 评论(0) 收藏
一.Berkeley DB的介绍 (1)Berkeley DB是一个嵌入式数据库,它适合于管理海量的.简单的数据.如Google使用其来保存账户信息,Heritrix用其来保存froniter. (2 ...
- 从Ecipse中导出程序至apk 分类: H1_ANDROID 2013-10-26 22:17 516人阅读 评论(0) 收藏
若未有数字证书: 1. 2. 3. 4. 5. 若已有数字证书: 上面的后3步改为 版权声明:本文为博主原创文章,未经博主允许不得转载.
- maven打包到本地库
mvn install:install-file -DgroupId=com.alipay -DartifactId=com.alipay.core -Dversion=20180104135026 ...
- [转载]Ocelot简易教程(三)之主要特性及路由详解
上篇<Ocelot简易教程(二)之快速开始2>教大家如何快速跑起来一个ocelot实例项目,也只是简单的对Ocelot进行了配置,这篇文章会给大家详细的介绍一下Ocelot的配置信息.希望 ...
- 【35.00%】【z13】&&【b093】最优贸易
[题解] 这题就是要在n个点里面选一个花费最小的点.然后找一个花费最大的点.两者之差为最大值. 但是最大值的点要在最小值的点之后出现.且走到后者之后要能够到达N号节点.为了处理掉环.先用tarjan进 ...
- ajax跳转到新的jsp页面(局部刷新)
ajax可以实现局部刷新页面,即在不刷新整个页面的情况下更新页面的局部信息. 项目中遇到一个问题:在用户列表也,当点击某个按钮时需要去查询用户的信息,查询成功跳转到用户详情界面:查询失败,则在原页面弹 ...
- Qt 连接MySQL数据库(很多相关文章)
今天想试试Qt如何连接数据库的. 谁知怎么写完了提示driver not loaded我就郁闷了. 我自己是 VS2010 + Qt4.8.4 + MySQL5.1 的环境 网上查到是 C:\Qt\4 ...
- 简洁常用权限系统的设计与实现(五):不维护节点的深度level,手动计算level,构造树
这种方式,与第三篇中介绍的类似.不同的是,数据库中不存储节点的深度level,增加和修改时,也不用维护.而是,在程序中,实时去计算的. 至于后面的,按照level升序排序,再迭代所有的节点构造树,与 ...
- Web开发四大作用域(转)
Web开发中的四个域对象(范围由小到大): page(jsp有效) request(一次请求) session(一次会话) application(当前web应用) page域指的是pageCont ...
- 西方教育骗局,终于明白精英和普通人的残酷差别!(该校流传着一个数字——4。即“4小时睡眠、4杯咖啡、GPA4.0”——要想获得满分为4分的成绩,每天只睡4个小时,困了就喝4大杯咖啡)
2018-02-14 00:00英国/私立学校 你不知道的是:西方教育通过一个宽松的过程,偷偷完成了社会分层. 1 “中国学生真是太苦了!”我的同学李女士总是发出这样的感慨. 李女士是我中学同学,在一 ...