前言
因为要准备面试,我复习c/c++基础的时候,发现对这两个函数的实现机制理解不够到位。所有我决定用隐性链表实现一个简单的malloc.
malloc实现原理
原本想画图,但是太懒。感觉语言解释会比较麻烦,我还是直接上代码吧。
struct memBlock{
int size; //分配的内存块大小。
int is_free; //0空闲 1被占用
};
malloc其实采用内存池的方式,先申请大块内存作为堆区,然后将堆区分为多个内存块,以块作为内存管理的基本单位。当用户申请内存时,直接从堆区分配一块合适的空闲块。(关于这方面个人推荐stl源码剖析)为了方便管理,会将这些空闲块,连接为一个隐性空闲链表,当需要分配时会根据一定规则选择一个内存块分配。我这里采用首次适应算法
#pragma once
#include<iostream>
#include<malloc.h>
#define ALIGNMENT 8
#define HEAP_SIZE 10000
using namespace std;
struct memBlock{
int size;
int is_free; //0空闲 1被占用
};
class Malloc {
private:
int init_Heap();
void* simple_malloc(size_t size);
int merge_free_blocks();
bool heap_inited;
memBlock *Heap;
void * heap_star_addr;
void * heap_end_addr;
public:
Malloc();
int simple_free(void* p);
void* _simple_malloc(size_t size);
void print_heap_info();
};
最近沉迷多文件编程,对封装有点特别的热情。
#include"Malloc.h"
Malloc::Malloc() {
this->heap_star_addr = 0;
this->heap_end_addr = 0;
this->heap_inited = true;
}
/*
int Malloc::init_Head()
用于初始化堆
成功返回 0
失败返回 -1
*/
int Malloc::init_Heap() {
heap_inited = false;
heap_star_addr = malloc(HEAP_SIZE);
if (heap_star_addr == 0)
return -1;
Heap = (memBlock*)heap_star_addr;
Heap->size = HEAP_SIZE;
Heap->is_free = 0;
heap_end_addr = (void*)((char*)heap_star_addr + HEAP_SIZE - 1);
cout << "初始申请内存起始位置 --- " << Heap << " --- " << heap_star_addr << endl;
return 0;
}
void* Malloc::simple_malloc(size_t size) {
if (heap_star_addr == 0)
return 0;
size = (size + ALIGNMENT - 1) & (~(ALIGNMENT - 1)); // 对齐内存
while ((void *)Heap < heap_end_addr) {
if (!Heap->is_free && Heap->size >= sizeof(memBlock) + size) {
if (Heap->size == (sizeof(memBlock) + size))
Heap->is_free = 1;
else {
memBlock * next_heap = (memBlock*)((char*)Heap + size + sizeof(memBlock));
next_heap->is_free = 0;
next_heap->size = Heap->size - sizeof(memBlock) - size;
Heap->is_free = 1;
Heap->size = sizeof(memBlock) + size;
cout << "被分配内存起始地址 : " << Heap << endl;
cout << "未分配内存起始地址 : " << next_heap << endl;
}
return (void*)((char*)Heap + sizeof(memBlock));
}
else
Heap = (memBlock*)((char*)Heap + Heap->size);
}
return 0;
}
int Malloc::merge_free_blocks() {
memBlock *block = (memBlock*)heap_star_addr;
while ((void *)((char*)block + block->size) < heap_end_addr) {
memBlock *next_block = (memBlock*)((char*)block + block->size);
if (!block->is_free && !next_block->is_free) {
block->size += next_block->size;
}
block = next_block;
}
return 0;
}
int Malloc::simple_free(void *p) {
memBlock *c = (memBlock*)((char*)p - sizeof(memBlock));
c->is_free = 0;
return 0;
}
void* Malloc::_simple_malloc(size_t size) {
if(heap_inited)
init_Heap();
void* p = simple_malloc(size);
if (p)
return p;
merge_free_blocks();
return simple_malloc(size);
}
void Malloc::print_heap_info() {
memBlock * a = (memBlock*)heap_star_addr;
cout << "start" << endl;
while ((void*)a <= heap_end_addr) {
cout << "开始地址 : " << a << "大小 : " << a->size << " 状态(0空闲) " << a->is_free << endl;
a = (memBlock*)((char*)a + a->size );
}
cout << endl;
}
void main() {
Malloc m;
m._simple_malloc(3000);
m.print_heap_info();
m._simple_malloc(4000);
//m.simple_free(a);
m.print_heap_info();
}
return (void*)((char*)Heap + sizeof(memBlock));
free之所以知道应该释放内存的大小,在于malloc申请内存的时候会多申请(x64 16字节)存放大小。这里简单模拟