libc 内存申请和释放及堆连续检查
2016-08-04 17:18
429 查看
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+1); //强制转换
内存释放函数(用来释放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。申请大内存快的好处是避免碎片化。
关于内存对齐
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 内存申请和释放及堆连续检查
- 内存申请和释放及堆连续
- 内存申请和释放及堆连续
- wildmagic 内存连续的多维数组申请与释放
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- 在DLL中用CRT静态库申请内存,EXE释放是不行的
- c++/c内存申请与释放
- 安全的代码之内存的申请和释放
- iOS 视图控制器的内存申请与释放普遍规则
- C 笔记 free()释放一个非malloc() 申请的内存
- 费解,为什么申请的内存没有被释放?约瑟夫环
- 用vs2008写了一个动态库,其中有申请内存,用vc6.0写了一个exe调用动态库,并释放dll申请的内存:dbgheap.c Line:1011
- C语言使用回调函数解决内存申请和释放的问题
- 指针,变量的生存期及作用范围,良好的动态内存申请和释放习惯
- C语言连续申请变量内存问题
- 挖一下那些年的东东(模拟内存申请与释放C语言)
- /MT、/MD编译选项,以及可能引起在不同堆中申请、释放内存的问题
- 内存的申请与释放
- DirectByteBuffer内存申请与释放 && 可能会导致内存泄露的原因
- 释放动态申请的内存