C语言可以使用alloc从栈上动态分配内存。

内存碎片

Malloc/free或者new/delete大量使用会造成内存碎片,这种碎片形成的机理如下:

内存碎片一般是由于空闲的内存空间比要连续申请的空间小,导致这些小内存块不能被充分的利用,举个例子:

如果有100个单位的连续空闲内存,那么先申请3单元的连续内存,再申请50单元的内存,这时释放一开始的3单元的内存。这时,如果你一直申请比三单元大的内存单元,那么开始的那连续的三单元就一直不能被使用。

一个简单的内存池的写法:

struct memblock

{

int              used;

void*            data;

struct memblock* next;

struct memblock* createnext;

};

struct mempool
{
    int            size;//memblock大小
    int            unused;//空闲的memblock大小
    int            datasize;//每次分配的数据大小(就是memblock.data)
    struct memblock*    free_linkhead;//空闲memblock链表头
    struct memblock*    create_linkhead;//所有创建的memblock链表头,内存池释放的时候使用,防止内存池释放的似乎还有memblock未归还的情况
    
};

typedef void (*free_callback)(void*);//释放回调函数,释放membloc.data用,可以简单的直接用free函数

void    mempool_init(int initialSize,int datasize);//初始化mempool
void    mempool_dealloc(struct mempool* pool,free_callback callback);//释放mempool
void*    mempool_get(struct mempool* pool);//获取一个memblock
void    mempool_release(struct mempool* pool,struct memblock* block);//归还一个memblock

/*********************************
 * mempool
 * ******************************/
//malloc一个memblock
static struct memblock* mempool_allocblock( struct mempool* pool );

//------------------implement--------
void*
mempool_init( int initialSize, int datasize )
{
    struct mempool* pool = malloc( sizeof( struct mempool ) );
    pool->unused = 0;
    pool->datasize = datasize;
    pool->free_linkhead = NULL;
  
    //预先初始化initialSize个内存块
     pool->create_linkhead = NULL;
    int i;
    for ( i = 0; i < initialSize; i++ ) {
        struct memblock* block = mempool_allocblock( pool );
        mempool_release( pool, block );
    }
    return ( pool );
}

void
mempool_dealloc( struct mempool* pool, free_callback callback )
{
    struct memblock* block = NULL;
    //将所有创建的memblock释放了
    while ( pool->create_linkhead != NULL ) {
        block = pool->create_linkhead;
        pool->create_linkhead = pool->create_linkhead->createnext;
    //执行free回调。
        if ( callback ) {
            ( *callback )( block->data );
        }
        free( block );
    }
    free( pool );
    L_DEBUG( "%s:size(%d),unused(%d)", __func__, pool->size, pool->unused );
}

static struct memblock*
mempool_allocblock( struct mempool* pool )
{
    struct memblock* block = malloc( sizeof( struct memblock ) );
    block->data = malloc( sizeof( pool->datasize ) );
    block->next = NULL;
    block->used = 1;//表示已使用

//加入所有创建的memblock的链表头
    block->createnext = pool->create_linkhead;
    pool->create_linkhead = block;

pool->size++;
    return ( block );
}

void
mempool_release( struct mempool* pool, struct memblock* block )
{
    if ( block == NULL ) {
        L_WARN( "%s:release a NULL!", __func__ );
        return;
    }
    if ( block->used != 1 ) {
        L_WARN( "%s:used!=1", __func__ );
        return;
    }
    //将归还的内存块放到空闲链表头。
    block->used = 0;//表示空闲
    block->next = pool->free_linkhead;
    pool->free_linkhead = block;
    pool->unused++;//空闲数+1
}

void*
mempool_get( struct mempool* pool )
{
   
    struct memblock* block = NULL;
    if ( pool->free_linkhead ) {
    //从空闲链表头取出一个内存块
        block = pool->free_linkhead;
        pool->free_linkhead = pool->free_linkhead->next;
        block->next = NULL;
        block->used = 1;//表示已使用
        pool->unused--;//空闲内存块数-1
    }
    else {
    //没有空闲的内存块,创建一个
        block = mempool_allocblock( pool );
    }
    return ( block );
}

C语言内存管理(内存池)的更多相关文章

  1. [译]Unity3D内存管理——对象池(Object Pool)

    原文地址:C# Memory Management for Unity Developers (part 3 of 3), 其实从原文标题可以看出,这是一系列文章中的第三篇,前两篇讲解了从C#语言本身 ...

  2. Spark内核| 调度策略| SparkShuffle| 内存管理| 内存空间分配| 核心组件

    1. 调度策略 TaskScheduler会先把DAGScheduler给过来的TaskSet封装成TaskSetManager扔到任务队列里,然后再从任务队列里按照一定的规则把它们取出来在Sched ...

  3. Java中的垃圾回收机制&内存管理&内存泄漏

    1. Java在创建对象时,会自动分配内存,并当该对象引用不存在的时候,释放这块内存. 为什么呢? 因为Java中使用被称为垃圾收集器的技术来监视Java程序的运行,当对象不再使用时,就自动释放对象所 ...

  4. 【原创】android内存管理-内存泄漏原因

    转载请注明出处 http://www.cnblogs.com/weiwangnuanyang/p/5704596.html 先讲一下内存泄漏的概念:内存泄露是指无用对象持续占有内存,或者内存得不到及时 ...

  5. 内存管理 & 内存优化技巧 浅析

    内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户 ...

  6. 构造函数,C++内存管理,内存泄漏定位

    构造函数 1.构造顺序 虚基类构造函数,基类构造函数,类对象构造函数,自己的构造函数 2.必须使用初始化列表 (1) 引用成员,常量成员: (2) 基类没默认构造函数(自己重载覆盖了), (3)类对象 ...

  7. Linux内核内存管理-内存访问与缺页中断【转】

    转自:https://yq.aliyun.com/articles/5865 摘要: 简单描述了x86 32位体系结构下Linux内核的用户进程和内核线程的线性地址空间和物理内存的联系,分析了高端内存 ...

  8. JVM内存管理------JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  9. JVM内存管理之JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  10. 黑马程序员——OC语言 内存管理

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)计数器 每个对象内部都保存了一个与之相关联的整数,称为引用计数器,当 ...

随机推荐

  1. window git安装 以及 tortoiseGit安装与使用

    一:Git安装 使用TortoiseGit这个程序,需要先安装Git Windows版本Git的下载页面: http://git-scm.com/download/win 1:下载Git到文件夹, 2 ...

  2. Kubernates之从pod中拷贝文件到宿主机

    想从k8s的pod中拷贝文件到宿主机,kubectl 的cp命令,但是网上搜索了下,感觉有点乱,自己记录下. hadoop这个namespace下,有个hadoop-hadoop-yarn-rm-0的 ...

  3. JVM之java并发 ——线程安全与锁优化

    概述 人们很难想象现实中的对象在一项工作进行期间,会被不停地中断和切换,对象的属性(数据)可能会在中断期间被修改和变“脏”,而这些事情在计算机世界中则是很正常的事情.有时候,良好的设计原则不得不向现实 ...

  4. xorm -sum 系列方法实例

    求和数据可以使用Sum, SumInt, Sums 和 SumsInt 四个方法,Sums系列方法的参数为struct的指针并且成为查询条件. package main import ( " ...

  5. Spring Cloud--Hystrix服务熔断(线程隔离/服务降级)代码实现

    一旦服务阻塞就进行服务降级或线程隔离.要不然就会导致大面积服务的瘫痪,Hystrix就是干这个的,一出现不健康的服务就进行熔断,不阻塞后面线程的执行. 引入依赖: 加注解: 这三个注解可以用一个注解搞 ...

  6. python基础_MySQL的bigint类型

    bigint支持的数字的大小范围为:19位,存电话号码.有符号范围:-9223372036854775808 到 9223372036854775807 int支持的数字范围为:10位,有符号范围:- ...

  7. [UOJ #140]【UER #4】被粉碎的数字

    题目大意:定义$f(x)$为数字$x$每一位数字的和,求$\sum\limits_{i=1}^R[f(x)=f(kx)]$.$R\leqslant10^{18},k\leqslant10^3$ 题解: ...

  8. [洛谷P5329][SNOI2019]字符串

    题目大意:给一个长度为$n$的字符串$s$,字符串$p_i$为字符串$s$去掉第$i$个字符后形成的字符串.请给所有字符串$p_i$排序(相同字符串按编号排序) 题解:先去掉所有连续相同字符,因为它们 ...

  9. LOJ2482 CEOI2017 Mousetrap 二分答案、树形DP

    传送门 表示想不到二分答案qwq 将树看作以陷阱为根.先考虑陷阱和起始点相邻的情况,此时老鼠一定会往下走,而如果管理者此时不做操作,那么一定会选择让操作次数变得最大的一棵子树.设\(f_i\)表示当前 ...

  10. STL之 stack的基础应用

    头文件 #include<stack> stack<int>  s; stack<char> s;//定义一个名字为s 的存int char的stack 基本指令 ...