C语言内存管理(内存池)
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语言内存管理(内存池)的更多相关文章
- [译]Unity3D内存管理——对象池(Object Pool)
原文地址:C# Memory Management for Unity Developers (part 3 of 3), 其实从原文标题可以看出,这是一系列文章中的第三篇,前两篇讲解了从C#语言本身 ...
- Spark内核| 调度策略| SparkShuffle| 内存管理| 内存空间分配| 核心组件
1. 调度策略 TaskScheduler会先把DAGScheduler给过来的TaskSet封装成TaskSetManager扔到任务队列里,然后再从任务队列里按照一定的规则把它们取出来在Sched ...
- Java中的垃圾回收机制&内存管理&内存泄漏
1. Java在创建对象时,会自动分配内存,并当该对象引用不存在的时候,释放这块内存. 为什么呢? 因为Java中使用被称为垃圾收集器的技术来监视Java程序的运行,当对象不再使用时,就自动释放对象所 ...
- 【原创】android内存管理-内存泄漏原因
转载请注明出处 http://www.cnblogs.com/weiwangnuanyang/p/5704596.html 先讲一下内存泄漏的概念:内存泄露是指无用对象持续占有内存,或者内存得不到及时 ...
- 内存管理 & 内存优化技巧 浅析
内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户 ...
- 构造函数,C++内存管理,内存泄漏定位
构造函数 1.构造顺序 虚基类构造函数,基类构造函数,类对象构造函数,自己的构造函数 2.必须使用初始化列表 (1) 引用成员,常量成员: (2) 基类没默认构造函数(自己重载覆盖了), (3)类对象 ...
- Linux内核内存管理-内存访问与缺页中断【转】
转自:https://yq.aliyun.com/articles/5865 摘要: 简单描述了x86 32位体系结构下Linux内核的用户进程和内核线程的线性地址空间和物理内存的联系,分析了高端内存 ...
- JVM内存管理------JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- JVM内存管理之JAVA语言的内存管理概述
引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...
- 黑马程序员——OC语言 内存管理
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)计数器 每个对象内部都保存了一个与之相关联的整数,称为引用计数器,当 ...
随机推荐
- linux升级python到2.7版本
linux的python安装包默认版本是2.6.6,yum程序默认也是依赖这个版本的python包的,但是其他一些程序如nodejs,却要的是2.7版本,因此必须要考虑升级后与yum的兼容问题.两步走 ...
- Docker容器(六)——创建docker私有化仓库
docker私有化仓库是为了节约带宽(外网速度慢或者干脆不能连外网),以及自己定制系统. (1).环境 youxi1 192.168.5.101 docker私有化仓库 youxi2 192.168. ...
- 大名鼎鼎的UniDAC手工安装
第一次开博,该写点什么.由于懒,很多事情,都不想动.不过,懒不能解决遗忘的毛病.还是动手,记录一下吧. 好了,言归主题. UniDAC 的手工安装. 现在Delphi,已经发展到了XE6,支持多种移动 ...
- [LeetCode] 504. Base 7 基数七
Given an integer, return its base 7 string representation. Example 1: Input: 100 Output: "202&q ...
- 【Python学习之二】Python基础语法
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 python3.6 一.Python的注释及乱码1.单行注释:以#开头 ...
- php_mvc实现步骤七
shop34-5-登录表单 登录功能分析 功能:登录表单 C控制器-动作 back后台admin控制器loginAction动作完成该功能. Application/back/controller/A ...
- R统计数据框的行数
如下三种方法可以实现 使用dim函数 dim(dataframe)[0] 使用nrow函数 nrow(dataframe) 使用length函数统计 length(dataframe[,1])
- JAVAWEB实现增删查改(图书信息管理)之添加功能实现
addBooks.jsp页面代码:↓ <%-- Created by IntelliJ IDEA. User: NFS Date: 2019-7-12 Time: 14:30 To change ...
- python使用matplotlib在一个图形中绘制多个子图以及一个子图中绘制多条动态折线问题
在讲解绘制多个子图之前先简单了解一下使用matplotlib绘制一个图,导入绘图所需库matplotlib并创建一个等间隔的列表x,将[0,2*pi]等分为50等份,绘制函数sin(x).当没有给定x ...
- WPF 程序如何跨窗口/跨进程设置控件焦点
原文:WPF 程序如何跨窗口/跨进程设置控件焦点 WPF 程序提供了 Focus 方法和 TraversalRequest 来在 WPF 焦点范围内转移焦点.但如果 WPF 窗口中嵌入了其他框架的 U ...