malloc,free简单的实现
malloc函数分配内存时会附加若干(一般是12个)字节,存放控制信息。
该信息一旦被意外损坏,可能在兴许操作中引发异常。
brk/sbrk 底层维护一个指针,记录所分配的内存结尾,所分配内存位于堆中,底层调用mmap/munmap。
malloc 底层维护一个双向链表和必要的控制信息,不可越界訪问。所分配内存位于堆中,底层调用brk/sbrk。
每一个进程都有4G的虚拟内存空间。虚拟内存地址仅仅是一个数字,并没有和实际的物理内存相关联。
所谓内存分配与释放,其本质就是建立或取消虚拟内存和物理内存间的映射关系。
sbrk (
intptr_t increment // 内存增量(以字节为单位)
);
0 - 获取末尾地址。
>0 - 添加内存空间。
<0 - 释放内存空间。
内部维护一个指针。指向当前堆内存最后一个字节的下一个位置。
sbrk函数依据增量參数调整该指针的位置,同一时候返回该指针原来的位置。
若发现页耗尽或空暇。则自己主动追加或取消页映射。
brk (
);
成功返回0。失败返回-1。
内部维护一个指针,指向当前堆内存最后一个字节的下一个位置。
brk函数依据指针參数设置该指针的位置。
若发现页耗尽或空暇。则自己主动追加或取消页映射。
简便起见,可用sbrk分配内存。用brk释放内存。
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
typedef struct mem_control_block //内存控制块
{
bool free; //自由标志
struct mem_control_block* prev; //前向指针
size_t size; //块大小
}MCB;
MCB* g_top; //内存栈顶指针 // +----------------------+ g_top
// v | |
// +------+------------+--|---+------------+------+------------+
// | prev | | prev | | prev | |
// | free | | free | | free | |
// | size | | size | | size | |
// +------+------------+------+------------+------+------------+
// MCB |<-- size -->| void* my_malloc(size_t size)
{
MCB* mcb;
for(mcb = g_top; mcb; mcb = mcb->prev)
if(mcb->free && mcb->size >= size)//寻找可用空块
break;
if(!mcb) //假设没有可用空块
{
mcb = sbrk(sizeof(MCB) + size); //增量分配size大小内存
if(mcb == (void*)-1) //假设分配失败,打印错误信息
{
perror("sbrk");
return NULL;
}
mcb->prev = g_top; //调整前向指针
mcb->size = size; //大小
g_top = mcb; //调整栈顶指针
}
mcb->free = false; //不管用原来空块还是新分配的块,都标记为不可用
return mcb + 1; //返回实际分配的内存起始地址
}
void my_free(void* ptr)
{
if(!ptr)
return; MCB* mcb = (MCB*)ptr - 1; //取控制块起始地址,
//注意:ptr为实际可用内存起始地址
mcb->free = true; //块标记为可用 //在栈中查找连续内存块
for(mcb = g_top; mcb->prev; mcb = mcb->prev)
if(!mcb->free)
break;
//释放整个栈全部内存块
if(mcb->free)
{
g_top = mcb->prev;
brk(mcb); //改动内存块末尾地址
}
else //释放连续的标记为true的内存块
{
g_top = mcb;
brk((void*)mcb + sizeof(MCB) + mcb->size);
}
}
//測试
int main(void)
{
int* pa[10];
size_t size = sizeof(pa) / sizeof(pa[0]), i, j;
for(i = 0; i < size; ++i)
{
if(!(pa[i] = (int*)my_malloc((i+1) * sizeof(int))))
{
perror("my_malloc");
return -1;
}
for(j = 0; j <= i; ++j)
pa[i][j] = j;
}
for(i = 0; i < size; ++i)
{
for(j = 0; j <= i; ++j)
printf("%d ", pa[i][j]);
printf("\n");
}
for(;;)
{
my_free(pa[--i]);
if(! i)
break;
}
return 0;
}
版权声明:本文博主原创文章,博客,未经同意不得转载。
malloc,free简单的实现的更多相关文章
- new与malloc
首先将new与malloc的区别总结如下: 1 new可以自动计算需要分配多大的内存,而malloc必须指明. 2 new返回的指针是有类型的,malloc返回void*类型的指针. 3 new在分配 ...
- 简单来谈谈alloc分配器
之前说道alloc是原G2.9版本的默认的分配器,这篇就把alloc的原理梳理梳理,顺便简单介绍下有关的内存管理. 一般而言,我们通常习惯的内存分配操作和释放操作是这样的: class Foo {…} ...
- 从内部入手,浅谈malloc和new的区别
想要理解一样事物,就要先用自己的语言去描述一件事物.在我查阅资料后,发现malloc函数简单说来就是空闲内存空间收集器,并把空闲空间关联起来,用术语来说就是:将空闲内存块合并起来并称为"闲置 ...
- C语言内存分配函数malloc——————【Badboy】
C语言中经常使用的内存分配函数有malloc.calloc和realloc等三个,当中.最经常使用的肯定是malloc,这里简单说一下这三者的差别和联系. 1.声明 这三个函数都在stdlib.h库文 ...
- new/delete与malloc/free的区别
new/delete与malloc/free的区别 参考: https://blog.csdn.net/u013485792/article/details/51329541 https://www. ...
- malloc实现机制
使用过c语言的都知道malloc是一个动态分配内存的函数,还可以通过free释放内存空间. 如果我们想分析一下malloc的源码,这其实不是一会就能看懂的,但是我们可以讨论一下malloc的简单实现. ...
- STL—内存的配置与释放
上一篇我们介绍了STL对象的构造与析构,这篇介绍STL内存的配置与释放. STL有两级空间配置器,默认是使用第二级.第二级空间配置器会在某些情况下去调用第一级空间配置器.空间配置器都是在allocat ...
- [自制操作系统] 连续页分配释放&kmalloc/kfree
本文将在JOS上实现连续内存.释放,提供内核的kmalloc与kfree,并在分配frambuffer的时候进行测试. Github : https://github.com/He11oLiu/JOS ...
- STL源码剖析(空间配置器)
前言 在STL中,容器的定义中都带一个模板参数,如vector template <class T, class Alloc = alloc> class vector {...} 其中第 ...
随机推荐
- rsync+inotify 实现资源服务器的同步目录下的文件变化时,备份服务器的同步目录更新,以资源服务器为准,去同步其他客户端
测试环境: 资源服务器(主服务器):192.168.200.95 备份服务器(客户端):192.168.200.89 同步目录:/etc/test 同步时使用的用户名hadoop密码12345 实验目 ...
- 写一个 docker 打击一系列手册
感谢您的关注,分享也再次给自己一个学习的.机会组织和总结.对未来一段时间内准备一个关于 docker 一系列的实际应用,其中的一些内容此前曾宣布.准备再次修改和整理. 以下是主要的文件夹中的一个: 创 ...
- 【Web探索之旅】第二部分第二课:服务器语言
内容简介 1.第二部分第二课:服务器语言 2.第二部分第三课预告:框架和内容管理系统 第二部分第二课:服务器语言 介绍了Web的客户端,我们来谈谈Web的服务器端. 既然客户端有客户端的编程语言(HT ...
- 【剑指offer】面试题28:弦乐
def Permutation(data, i): if len( data ) == 0: return # i stand for the start of first part for i in ...
- 使用WSE实现Web Service安全----我的第一篇
原文:使用WSE实现Web Service安全----我的第一篇 WSE(Web Services Enhancements)是微软为了使开发者通过.NET创建出更强大,更好用的Web Service ...
- table插入标签form标记怪现象
最近帮朋友处理问题,它无法提交表单,得到一些时间,我发现了一个奇怪的问题 <table> <form action="upload.php" method=&qu ...
- unity3d c# 产生真正的随机数
虽然能够使用Random类来生成随机数.但它是系统时钟种子,因此,有大量的反复产生伪随机数的. 您可以使用RNGCryptoServiceProvider();相对真随机数生成. 由加密服务提供程序( ...
- MFC9.0 Outlook控件的标题显示无法改动
这是我在开发中遇到的问题,现记录下来,以便帮助你们. 不想看废话的能够仅仅看最后三行,但你会错过非常多. 俗话说的好啊,"Wise men learn by other men's mist ...
- Gradle 载入中 Android 下一个.so档
1.在project下新建 jni/libs 目录 . jni 是和原来的libs 同级 ,将全部的.so文件放入 新建的libs文件下 2.在build.gradle 文件里新增下面内容到a ...
- 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 print-all-combinations-of-given-length
// 给定一个set字符和一个正数k,找出所有该做set它可以由长度构成k该字符串集合 /* Input: set[] = {'a', 'b'}, k = 3 Output: aaa aab aba ...