我写了一个自定义内存分配器。它有2个限制,我想删除所以它的工作方式类似malloc / free。
1。)mem_free调用需要为其输入参数强制转换为unsigned char *。我希望它采用任何类型的指针。怎么办呢?
2.。)我写的内存分配器为缓冲区的前面分配了一块内存,并且还写入了它的大小。 free函数删除缓冲区中最后一块已分配的内存。所以malloc / free调用的顺序很重要或者它不起作用。如何删除此限制?
希望能够做到这一点:
char* ptr1 = mem_alloc(10);
char* ptr2 = mem_alloc(4);
mem_free(ptr1);
mem_free(ptr2);
现在必须这样做:
char* ptr1 = mem_alloc(10);
char* ptr2 = mem_alloc(4);
mem_free(ptr2);
mem_free(ptr1);
代码:
unsigned char* mem_alloc(unsigned int size) {
unsigned int s;
if( (size + MEM_HEADER_SIZE) > (MEM_MAX_SIZE - mem_current_size_bytes) ) {
return NULL;
}
if(is_big_endian() == 0) {
s = (mem_buff[3] << 24) + (mem_buff[2] << 16) + (mem_buff[1] << 8) + mem_buff[0];
} else {
s = (mem_buff[0] << 24) + (mem_buff[1] << 16) + (mem_buff[2] << 8) + mem_buff[3];
}
memcpy(mem_buff + mem_current_size_bytes, &size, sizeof(unsigned int));
unsigned char* result = mem_buff + (mem_current_size_bytes + MEM_HEADER_SIZE);
mem_current_size_bytes += MEM_HEADER_SIZE + size;
return result;
}
void mem_free(unsigned char* ptr) {
unsigned int i,s;
for(i=0; i<mem_current_size_bytes; i++) {
if( (char*)ptr == (char*)(mem_buff + i) ) {
if(is_big_endian() == 0) {
s = (*(ptr - 1) << 24) + (*(ptr - 2) << 16) + (*(ptr - 3) << 8) + *(ptr - 4);
} else {
s = (*(ptr - 4) << 24) + (*(ptr - 3) << 16) + (*(ptr - 2) << 8) + *(ptr - 1);
}
mem_current_size_bytes-=s;
mem_current_size_bytes-=MEM_HEADER_SIZE;
break;
}
}
}
答案 0 :(得分:5)
1)改为使用void * 2)将地址映射存储到已分配的块和未分配的块的单独映射。然后,您可以在分配的映射中查找正在释放的块,将其删除,然后将块添加到未分配的映射(确保将其与任何一侧的任何空闲块合并)。当然,这可能而且确实会导致内存碎片,但实际上这是不可避免的。
答案 1 :(得分:3)
只需在mem_free的参数中使用void *指针而不是char *。
为了使内存分配器能够在任何内存位置工作,你需要增加更多的复杂性...我建议研究如何管理内存堆,你会发现一些基本的方案来试用。
答案 2 :(得分:3)
你写道,你正在寻找想法,所以我附上了我在大学完成的一个项目,我们应该实现malloc()和free()...... 您可以看到我是如何做到这一点的,如果您愿意,可能会获得灵感或使用它。它肯定不是最快的实现,但相当容易, 应该没有错误; - )
(请注意,如果来自同一课程的人偶然遇到过这种情况 - 请不要使用它而是自己制作 - 因此许可证; - )
/*
* The 1st project for Data Structures and Algorithms course of 2010
*
* The Faculty of Informatics and Information Technologies at
* The Slovak University of Technology, Bratislava, Slovakia
*
*
* Own implementation of stdlib's malloc() and free() functions
*
* Author: mnicky
*
*
* License: modified MIT License - see the section b) below
*
* Copyright (C) 2010 by mnicky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* a) The above copyright notice and this permission notice - including the
* section b) - shall be included in all copies or substantial portions
* of the Software.
*
* b) the Software WILL NOT BE USED IN ANY WORK DIRECTLY OR INDIRECTLY
* CONNECTED WITH The Faculty of Informatics and Information Technologies at
* The Slovak University of Technology, Bratislava, Slovakia
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include <stdio.h>
typedef unsigned int MEMTYPE;
MEMTYPE *mem;
MEMTYPE memSize;
MEMTYPE avail; //1st index of the 1st free range
//return size of block
MEMTYPE blockSize(MEMTYPE x) {
return mem[x];
}
//return next free block
MEMTYPE next(MEMTYPE x) {
return mem[x + mem[x]];
}
//return index of pointer to next free block
MEMTYPE linkToNext(MEMTYPE x) {
return x + mem[x];
}
//initialize memory
void my_init(void *ptr, unsigned size) {
mem = (MEMTYPE *) ptr;
memSize = size / sizeof(MEMTYPE);
mem[0] = memSize - 1;
mem[memSize - 1] = memSize;
avail = 0;
}
//allocate memory
void *my_alloc(unsigned size) {
if (size == 0) { //return NULL pointer after attempt to allocate 0-length memory
return NULL;
}
MEMTYPE num = size / sizeof(MEMTYPE);
if (size % sizeof(MEMTYPE) > 0) num++;
MEMTYPE cur, prev; //pointer to (actually index of) current block, previous block
MEMTYPE isFirstFreeBeingAllocated = 1; //whether the first free block is being allocated
prev = cur = avail;
//testing, whether we have enough free space for allocation
test:
if (avail == memSize) { //if we are on the end of the memory
return NULL;
}
if (blockSize(cur) < num) { //if the size of free block is lower than requested
isFirstFreeBeingAllocated = 0;
prev = cur;
if (next(cur) == memSize) { //if not enough memory
return NULL;
}
else
cur = next(cur);
goto test;
}
if (blockSize(cur) == num) { //if the size of free block is equal to requested
if (isFirstFreeBeingAllocated)
avail = next(cur);
else
mem[linkToNext(prev)] = next(cur);
}
else { //if the size of free block is greater than requested
if (isFirstFreeBeingAllocated) {
if ((blockSize(cur) - num) == 1) //if there is only 1 free item left from this (previously) free block
avail = next(cur);
else
avail = cur + num + 1;
}
else {
if ((blockSize(cur) - num) == 1) //if there is only 1 free item left from this (previously) free block
mem[linkToNext(prev)] = next(cur);
else
mem[linkToNext(prev)] = cur + num + 1;
}
if ((blockSize(cur) - num) == 1) //if there is only 1 free item left from this (previously) free block
mem[cur] = num + 1;
else {
mem[cur + num + 1] = blockSize(cur) - num - 1;
mem[cur] = num;
}
}
return (void *) &(mem[cur+1]);
}
//free memory
void my_free(void *ptr) {
MEMTYPE toFree; //pointer to block (to free)
MEMTYPE cur, prev;
toFree = ((MEMTYPE *)ptr - (mem + 1));
if (toFree < avail) { //if block, that is being freed is before the first free block
if (((linkToNext(toFree) + 1) == avail) && avail < memSize) //if next free block is immediately after block that is being freed
mem[toFree] += (mem[avail] + 1); //defragmentation of free space
else
mem[linkToNext(toFree)] = avail;
avail = toFree;
}
else { //if block, that is being freed isn't before the first free block
prev = cur = avail;
while (cur < toFree) {
prev = cur;
cur = next(cur);
}
if ((linkToNext(prev) + 1) == toFree) { //if previous free block is immediately before block that is being freed
mem[prev] += (mem[toFree] + 1); //defragmentation of free space
if (((linkToNext(toFree) + 1) == cur) && cur < memSize) //if next free block is immediately after block that is being freed
mem[prev] += (mem[cur] + 1); //defragmentation of free space
else
mem[linkToNext(toFree)] = cur;
}
else {
mem[linkToNext(prev)] = toFree;
mem[linkToNext(toFree)] = cur;
}
}
}
尽可能使用少量空间进行元信息传输,因此分配的空间由分配范围的第一个节点中的数字标记,表示后面分配的节点数。
自由范围内的可用空间量由一个数字标记,表示后续(包括该节点)的空闲节点数,自由范围的最后一个节点包含下一个自由范围的第一个索引的数量 - 这样的(红色空间被分配,白色是免费的):
它可以像这样使用:
char region[30000000]; //space for memory allocation
my_init(region, 30000000); //memory initialization
var = (TYPE *) my_alloc(sizeof(TYPE)); //memory allocation
my_free((void *) var); //freeing the memory
答案 3 :(得分:2)