First, let's briefly talk about the implementation principle of malloc in the standard library: The standard library uses a two-way linked list to manage the memory dynamically allocated in the heap.
When the malloc function allocates memory, it will append several (usually 12) bytes to store control information.
If this information is accidentally damaged, an exception may occur in subsequent operations.
MMAP/munmap The underlying layer does not maintain anything, but returns a first address. The allocated memory is located
Heap .
BRK/sbrk The underlying layer maintains a pointer, recording the end of the allocated memory, and the allocated memory is located
Heap The underlying layer calls MMAP/munmap.
Malloc The underlying layer maintains a two-way linked list and necessary control information, which cannot be accessed across borders. The allocated memory is located in
Heap The underlying layer calls BRK/sbrk.
Each process has 4 GB of virtual memory space. The virtual memory address is only a number and is not associated with the actual physical memory.
The essence of memory allocation and release is
Establishes or cancels the ing between virtual memory and physical memory. .
Several functions used: void *
Sbrk (
Intptr_t increment // memory increment (in bytes)
); Returns the end address of the last call to BRK/sbrk, and returns-1 if the call fails.
Value of increment:
0-get the end address.
> 0-increase memory space.
<0-release memory space.
Internally maintains a pointer pointing to the next location of the last byte of the current heap memory.
The sbrk function adjusts the pointer position based on incremental parameters and returns the original position of the pointer.
If the page is found to be exhausted or idle, page ing is automatically appended or canceled.
Int
BRK (Void * end_data_segment // address at the end of the memory block
);
0 is returned for success, and-1 is returned for failure.
Internally maintains a pointer pointing to the next location of the last byte of the current heap memory.
The BRK function sets the pointer position based on the pointer parameter.
If the page is found to be exhausted or idle, page ing is automatically appended or canceled.
The bottom layer of the sbrk/BRK maintains a pointer position, allocating and releasing virtual memory in units of pages (4 K.
For simplicity,
Allocate memory with sbrk and release memory with 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;}
Simple implementation of malloc and free