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 内存申请和释放及堆连续检查的更多相关文章

  1. Unity内存申请和释放

    转自:http://www.jianshu.com/p/b37ee8cea04c 1.资源类型 GameObject, Transform, Mesh, Texture, Material, Shad ...

  2. C语言学习之我见-malloc和free内存申请及释放函数

    malloc函数负责向计算机申请确定大小的内存空间. free函数负责释放malloc的申请空间. (1)函数原型 void free(void *_Memory); void * malloc(si ...

  3. C语言动态内存的申请和释放

    什么是动态内存的申请和释放? 当程序运行到需要一个动态分配的变量时,必须向系统申请取得堆中的一块所需大小的存储空间,用于存储该变量.当不再使用该变量时,也就是它的生命结束时,要显式释放它所占用的存储空 ...

  4. [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 ...

  5. Win3内存管理之私有内存跟共享内存的申请与释放

    Win3内存管理之私有内存跟共享内存的申请与释放 一丶内存简介私有内存申请 通过上一篇文章.我们理解了虚拟内存与物理内存的区别. 那么我们有API事专门申请虚拟内存与物理内存的. 有私有内存跟共享内存 ...

  6. C++函数中,两个自动释放内存的动态内存申请类

    最近做一个事情,实现一个流程交互,其中主交互流程函数中,涉及较多的内存申请, 而健康的函数,都是在函数退出前将手动申请不再需要的内存释放掉, 使用很多方法,都避免不了较多的出错分支时,一堆的if fr ...

  7. 内存管理概述、内存分配与释放、地址映射机制(mm_struct, vm_area_struct)、malloc/free 的实现

    http://blog.csdn.net/pi9nc/article/details/23334659 注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料 ...

  8. glibc内存管理那些事儿

    本文转载自glibc内存管理那些事儿 Linux内存空间简介 32位Linux平台下进程虚拟地址空间分布如下图: 进程虚拟地址空间分布 图中,0xC0000000开始的最高1G空间是内核地址空间,剩下 ...

  9. 2万字|30张图带你领略glibc内存管理精髓(因为OOM导致了上千万损失)

    前言 大家好,我是雨乐. 5年前,在上家公司的时候,因为进程OOM造成了上千万的损失,当时用了一个月的时间来分析glibc源码,最终将问题彻底解决. 最近在逛知乎的时候,发现不少人有对malloc/f ...

随机推荐

  1. 在 Java 中如何进行 BASE64 编码和解码

    BASE64 编码是一种常用的字符编码,在很多地方都会用到.JDK 中提供了非常方便的 BASE64Encoder 和 BASE64Decoder,用它们可以非常方便的完成基于 BASE64 的编码和 ...

  2. Windows Phone 8.1 联系人与日历

    (1)联系人(Manifest 获取权限) 1)获取联系人 获取联系人的方式有两种 A. ContactPicker ContactPicker 也就是直接打开一个系统的选择联系人界面,让用户选择,可 ...

  3. ios开发之多线程---GCD

    一:基本概念 1:进程:正在运行的程序为进程. 2:线程:每个进程要想执行任务必须得有线程,进程中任务的执行都是在线程中. 3:线程的串行:一条线程里任务的执行都是串行的,假如有一个进程开辟了一条线程 ...

  4. pthread_join/pthread_exit的使用方法解析

    官方说法: 函数pthread_join用来等待一个线程的结束.函数原型为: extern int pthread_join __P ((pthread_t __th, void **__thread ...

  5. js进阶 11-2 jquery属性如何操作

    js进阶 11-2  jquery属性如何操作 一.总结 一句话总结:jquery中的属性用attr方法表示.jquery中都是方法. 1.jquery中的属性的增删改查操作? 只需要两个方法, at ...

  6. iOS 利用FZEasyFile本地保存 和 常规保存

    1.常规保存(较麻烦) NSFileManager *fileManager = [NSFileManager defaultManager]; //获取document路径,括号中属性为当前应用程序 ...

  7. Oracle数据库零散知识02

    15,函数的创建,要求必须有返回值,必须在语句中调用,需要多个返回值时,使用out参数类型,在user_procedures表中查询属性,在user_source表中查询源代码,创建示例: CREAT ...

  8. ART、JIT、AOT、Dalvik之间有什么关系?

    JIT与Dalvik JIT是"Just In Time Compiler"的缩写,就是"即时编译技术",与Dalvik虚拟机相关. 怎么理解这句话呢?这要从A ...

  9. 【23.33%】【codeforces 664C】International Olympiad

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  10. SSH原理和使用

    ssh 是什么 在 linux 上工作,ssh 是必须要了解的技术方法.它可以建立起多台主机之间的安全的加密传输,以进行远程的访问.操控.传输数据. SSH 為 Secure Shell 的縮寫.為建 ...