关于C#:在指针指向的地址处创建结构

Creating a struct at address pointed by pointer

我有一个unsigned char* head指向内存中的某个addess,现在我必须创建一个在该指针的位置开始声明的typedef结构...我对如何执行此操作感到困惑!

这是typedef的声明

1
2
3
4
5
6
 typedef struct {
    struct block *next;
    struct block *prev;
    int size;
    unsigned char *buffer;
} block;

我的工作涉及实现malloc,所以我不能使用malloc。 一个块是free_list的一部分,该列表包含我程序堆中所有的空闲内存块。 因此,指向上一个和下一个空闲内存块的上一个和下一个指针。

标题指向free_list的开头。 当我必须拆分时,说第一块空闲内存来满足需要较少空间的malloc()请求,然后该空闲块需要我移动头部并在那里创建一个新的块结构。

希望这是有道理的。 如果没有,任务看起来像这样


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

1
2
3
4
5
6
 typedef struct block {
    struct block *next;
    struct block *prev;
    int size;
    unsigned char *buffer;
} block;

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

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

现在,只要正确地进行了铸造,您在地址head上就会有一个struct block

例如

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

或者,您为其分配强制转换指针:

1
2
block *p = (block *)head;
p->size = 5;

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

您的记录似乎正在执行免费列表。那么,当您还没有分配器时,如何分配列表节点呢?通常的解决方案是在空闲块本身中执行此操作。因此,自由块具有以下结构:

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

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

1
2
3
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)来建立分配器将管理的大块(通常称为"竞技场")就可以了。您还可以声明一个大字节数组。


来自评论:

head points to the start of a place in memory where I can overwrite data...You may assume that I have enough space!

然后获得正确键入的指针:

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

并获得该块的副本:

1
struct block b = *(struct block *)head;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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实例。
它的作用是创建一个块,然后将内存复制到磁头的位置,然后释放分配的块。