我正在使用空闲列表实现内存管理器,其节点是一个结构,包含有关要管理的内存块的元数据。
我会在一开始就调用malloc()一次从操作系统中获取一块内存。然后我将使用我自己的程序管理它。在后续程序中,我不能再使用malloc(),所以我必须将元数据(节点列表)保存在该内存中。这是我的问题,假设:
struct list *node1 = malloc(n_bytes); // only call malloc() once here
node1->memStart = node1 + sizeof(struct list) // beginning address of managable
// memory
node1->size = bytes_allocated;
node1->used = 1;
node1->next = NULL;
// starting address of node2
struct list *node2 = node1->memStart + node1->size; // used another node to track the second piece of
// that memory
node2->size = 4096;
node2->used = 0; // node2's memory is unused yet
node2->memStart = node2 + sizeof(struct list);
node2->next = NULL;
node1-next = node2; // link them
所以在这里我不确定我是否已将这些元数据(size,used,memStart,next)写入从node1开始的内存地址,从而使它看起来像:
----------<----node1
| size |
----------
| used |
----------
|memStart|------|
---------- |
| next | |
---------- |
| |<-----|
| mem |
| |
----------<----node2
| size |
----------
| used |
----------
|memStart|
----------
| next |
----------
| |
| mem |
| |
----------
所以我只是想知道上面的代码后,内存布局是否与上面绘制的一样。它主要是关于node2,我不确定我是否可以像这样使用它来将元数据写入内存。这很重要,因为随着越来越多的内存被分配,我需要更多的节点来跟踪它们。我认为没有malloc这样做的方法(否则编写我自己的经理没有意义)是做指针算术来将内存切成块并使用开销来跟踪它们。
列表的结构应该是:
struct list{
int size;
void *memStart;
int used;
struct list *next;
}
答案 0 :(得分:6)
不,内存布局不会像上面绘制的那样。考虑这一行:
node1->memStart = node1 + sizeof(struct list)
由于指针算术,node1 + x
将按x
缩放sizeof(*node1)
。也就是说,node1 + sizeof(struct list)
产生指向node1 + sizeof(struct list)*sizeof(struct list)
字节之外的地址的指针。这是C中的基本指针算法。你想要这个:
node1->memStart = ((char *) node1) + sizeof(struct list)
根据memStart
中struct list
的定义,这可能也是错误的:
struct list *node2 = node1->memStart + node1->size;
但是,如果您将memStart
声明为char *
,那么它应该有效,假设bytes_allocated
(您没有显示它是如何获得的)是正确的。
此行与node1
的等效行具有相同的错误:
node2->memStart = node2 + sizeof(struct list);