0

我有一个unsigned char* head指向内存中某个地址的指针,现在我必须创建一个 typedef 结构,我已经声明从该指针的位置开始......我对如何做到这一点感到困惑!

这是 typedef 的声明

 typedef struct {
    struct block *next;
    struct block *prev;
    int size;
    unsigned char *buffer;
} block;

我的任务涉及实现malloc,所以我不能使用malloc。块是 free_list 的一部分,它包含我在程序堆中拥有的所有空闲内存块块。因此,指向前一个和下一个空闲内存块的前一个和下一个指针。

Head 指向 free_list 的开始。当我必须拆分说第一个空闲内存块以满足需要更少空间的 malloc() 请求时,该空闲块有我需要移动我的头并在那里创建一个新的块结构。

希望这是有道理的。如果不是,则作业看起来像这样

4

4 回答 4

1

您的结构没有标签,因此您需要给它一个标签以使其指向自身:

 typedef struct block {
    struct block *next;
    struct block *prev;
    int size;
    unsigned char *buffer;
} block;

如果您使用的是 C99,您可以在head必要时直接初始化内存,而无需声明临时struct block:

*(block *)head = (block){NULL, NULL, 0, NULL};

只要你正确地投射它,你现在就有了struct blockat the address 。head

例如

((block *)head)->size = 5;

或者你为它分配一个强制转换指针:

block *p = (block *)head;
p->size = 5;
于 2013-03-23T22:44:53.690 回答
0

操作系统将提供一个 API 调用来分配您malloc可以分割并提供给调用者的内存块。在 Linux/unix 中查看sbrk. 在 Windows 中查看 Win32 堆 API。您的记录将指向此块。确保块的两个分配部分没有重叠是分配器代码的工作。

看起来您的记录正在实施免费列表。那么当你还没有分配器时,你将如何分配列表节点呢?通常的解决方案是在空闲块本身中进行。因此,空闲块具有以下结构:

typedef struct free_block {
    struct free_block *next, *prev;
    size_t size;
    unsigned char buffer[1];
} FREE_BLOCK;

现在这个数据结构实际上位于空闲块的开头。它的缓冲区在声明中只有 1 个字节,但实际缓冲区是size字节。最初你会有类似的东西:

static FREE_BLOCK *free_list = sbrk(ARENA_SIZE);
free_list->next = free_list->prev = free_list;
free_list->size = ARENA_SIZE - offsetof(FREEBLOCK, buffer);

这会将整个竞技场作为一个块放在空闲列表中。您的分配器将搜索free_list找到一个足够大的块,切出它需要的部分,将剩余的小块(如果有的话)放回空闲列表中。对于释放,它会将释放的块添加到列表中并合并相邻的块。

简单的空闲列表分配器在选择要分配的空闲块的方式上有所不同:首次适合、旋转首次适合、最佳适合、最差适合等。在实践中,旋转首次适合似乎与其他任何一种方法一样好或更好。

顺便说一句,所有用自由列表实现的常见算法都不需要双链接。单身的就可以了。

由于这是一项学术任务,因此只需调用malloc(而不是操作系统 API)来建立您的分配器将管理的大块(通常称为“竞技场”)应该没问题。您还可以声明一个大字节数组。

于 2013-03-23T22:36:14.300 回答
0
unsigned char* head = /* whatever you have assuming that it has a sufficient size. */;

/* Create a block in memory */
block* b = (block*)malloc(sizeof(block));

/*
*   modify data in b here as you wish.
*/
b->next = 0;
b->prev = 0;
/* etc... */

/* copy b to head */
memcpy(head, b, sizeof(block));

/* free block */
free(b);

上面假设 head 有足够的空间来存储一个 block 的实例。它所做的是创建一个块,并将内存复制到 head 的位置,然后释放分配的块。

于 2013-03-23T22:22:01.537 回答
0

来自评论:

head指向内存中可以覆盖数据的位置的开始...您可能会认为我有足够的空间!

然后获取正确类型的指针:

struct block *p = (struct block *)head;

并拥有该块的副本:

struct block b = *(struct block *)head;
于 2013-03-23T22:28:02.047 回答