我尝试在c中编写自己的自定义malloc和免费函数。我为此工作了大约12个小时,并尝试了很多东西。但它不起作用。也许你们能找出错误。分配的内存将从列表中删除,下一个指针指向特定地址,以便稍后在空闲函数中识别该地址。当前的误差是分割方法中的分割错误11。C-文件:
头:
#define MAGIC ((void*)0xbaadf00d)
#define SIZE (1024*1024*1)
typedef struct mblock {
struct mblock *next;
size_t size;
char memory[];
}mblock;
char memory[SIZE];
static struct mblock *head;
malloc:
void *halde_malloc (size_t size) {
printf("Startingn");
printf("%zun",size);
if(size <= 0) {return NULL;}
if(head == NULL){
initializeBlock();
printf("Memory initializedn");
}
mblock *temp_block = head;
while(temp_block != NULL) {
printf("INn");
if(temp_block->size == size) {
list_remove(temp_block);
temp_block->next = MAGIC;
return (void*)(temp_block);
} else if(temp_block->size > size) {
size_t temp_size = temp_block->size;
printf("size IS more than equaln");
list_split_AND_Remove(temp_size - size, temp_block);
temp_block->size = size;
temp_block->next = MAGIC;
return (void*)(temp_block);
}
temp_block = temp_block->next;
printf("One block checkedn");
}
errno = ENOMEM;
return NULL;
}
初始化:
void initializeBlock(){
printf("Initializingn");
head = (mblock*)memory;
head->size=sizeof(memory)-sizeof(mblock);
head->next=NULL;
}
拆分:
void list_split_AND_Remove(size_t size, mblock *lastBlock) {
printf("Splitn");
mblock *new = (void*)((mblock*)lastBlock+size+sizeof(mblock));
new->size = size - sizeof(mblock);
new->next = lastBlock->next;
lastBlock->next = new;
printf("START REMOVE");
list_remove(lastBlock);
}
删除:
void list_remove(mblock *p) {
printf("Removen");
mblock *temp_block = head;
if(p == head) {
if(head->next == NULL) {
head = NULL;
return;
} else {
head = p->next;
return;
}
}
while(temp_block->next != NULL) {
if(temp_block->next == p) {
printf("Found P:");
temp_block = p->next;
return;
}
temp_block = temp_block->next;
}
}
免费:
void halde_free (void *ptr) {
printf("FREEn");
mblock *new_block = ptr;
if(new_block->next == MAGIC) {
new_block->next = head;
head = new_block;
} else {abort();}
}
代码的问题包括但不一定限于:
-
list_remove()
实际上不会从列表中删除指定的块,除非它恰好是当前列表头。因此,在其他任何情况下,halde_malloc()
在修改节点的next
指针时都会在调用list_remove()
之后破坏列表。 -
list_split_AND_Remove()
执行不正确的指针运算。具体来说,mblock *new = (void*)((mblock*)lastBlock+size+sizeof(mblock));
不会执行您想要执行的操作,因为指针算术以指向类型的大小为单位进行运算,而size
参数和sizeof
运算符的结果则以单个字节为单位。(此外,这两种投射都是无用的,尽管它们本身无害。( -
分配器返回一个指向块头的指针,而不是指向它的数据。因此,用户很可能会覆盖块头的内容,从而在您稍后尝试释放该块时造成严重破坏。
-
您似乎假设
mblock
对象的对齐要求为1。这可能不是真的。