我尝试在c中编写自己的自定义malloc和free函数。我为此工作了大约12个小时,尝试了很多事情。但这是行不通的。 也许你们可以找出错误。使用下一个指向特定地址的指针从列表中删除已分配的内存,以便稍后在free函数中对其进行标识。当前的错误是分割方法中的分段故障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("Starting\n");
printf("%zu\n",size);
if(size <= 0) {return NULL;}
if(head == NULL){
initializeBlock();
printf("Memory initialized\n");
}
mblock *temp_block = head;
while(temp_block != NULL) {
printf("IN\n");
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 equal\n");
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 checked\n");
}
errno = ENOMEM;
return NULL;
}
初始化:
void initializeBlock(){
printf("Initializing\n");
head = (mblock*)memory;
head->size=sizeof(memory)-sizeof(mblock);
head->next=NULL;
}
拆分:
void list_split_AND_Remove(size_t size, mblock *lastBlock) {
printf("Split\n");
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("Remove\n");
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("FREE\n");
mblock *new_block = ptr;
if(new_block->next == MAGIC) {
new_block->next = head;
head = new_block;
} else {abort();}
}
答案 0 :(得分:3)
您的代码问题包括但不一定限于:
list_remove()
实际上不会从列表中删除指定的块,除非它恰好是当前列表的头。因此,在其他所有情况下,halde_malloc()
在修改节点的list_remove()
指针时调用next
后都会破坏列表。
list_split_AND_Remove()
执行不正确的指针算术。具体来说,mblock *new = (void*)((mblock*)lastBlock+size+sizeof(mblock));
并没有像您想做的那样做,因为指针算术以指向类型的大小为单位进行操作,而size
参数和{{1}的结果}运算符的单位为单个字节。 (此外,这两种类型的转换都是无用的,尽管它们本身对人体无害。)
您的分配器返回一个指向块头的指针,而不是指向其数据的指针。结果,用户很可能会覆盖块头的内容,从而在您以后尝试释放该块时造成严重破坏。
您似乎假设sizeof
对象的对齐要求为1。这可能不正确。