c固定内存池实现

时间:2019-03-26 14:19:18

标签: c

我正在尝试实现一个固定的内存池(第一个免费列表) 我的结构是:

struct mempool {
    void* data;
    int offset;
};

data分为8个字节的块,指向下一个偏移量的4个字节和4个字节的数据。 offset指向第一个空闲块。我试图了解为什么通过以下方式访问第一个块:

int* address = (int*)((int)&pool->data + pool->offset);

尤其是(int)&pool->data部分。池->数据不是指针吗?为什么我需要它的地址来执行算术运算并移至偏移量?

3 个答案:

答案 0 :(得分:2)

  

我试图理解为什么通过以下方式完成对第一个块的访问:

int* address = (int*)((int)&pool->data + pool->offset);
     

尤其是(int)&pool->data部分。 pool->data还不是   指针?

是的,pool->data是一个指针。而且可以获取指针的地址,因此这并没有本质上的错误。在这种情况下,结果的类型为void **

此外,假设datastruct mempool的第一个成员,则&pool将指向相同的地址。尽管后者具有不同的类型(struct mempool *),但可能是因为代码执行了对类型int的转换。

  

为什么我需要它的地址来执行算术运算并转移到   偏移量?

效果是相对于data指针本身的位置而不是相对于其 target 的位置来计算地址。此外,对类型int的强制转换建议以字节为单位测量偏移量。但是,这方面并不安全,因为不能保证类型int足以支持从指针到int到指针的往返转换。

这一切似乎与您对具有与数据相邻的元数据的池的特征保持一致,但仍不清楚data指针的作用是什么。

总体而言,尽管我不相信所展示的最小代码的正确性或有效性。如果相对于给出的结构定义,实际上它达到了预期的目的,那么这种变化应该做得更好,更清楚:

int* address = (int*)((char *)&pool + pool->offset);

这避免了可以表示指针的整数类型的问题(尽管以intptr_t的形式存在)。强制转换为char *的事实是,指针算术是以指向类型的大小为单位执行的,而偏移量似乎以一字节为单位表示。

答案 1 :(得分:1)

您的代码似乎不正确。您要将pool->offset添加到pool->data字段的地址,而不是添加到存储在pool->data字段中的地址。我建议像这样修复:

int* address = (int *)pool->data + pool->offset;

如果您的偏移量是4字节的块,或者像这样:

int* address = (int *)((char *)pool->data + pool->offset);

如果您的偏移量以字节为单位。

答案 2 :(得分:1)

pool->data + pool->offset是不可能的,因为您不能对void指针执行指针算术-这不是有效的C。指针算术还假定所有这些的基础类型是数组

&pool->data给出指针本身的地址,该地址恰好是结构的地址。类型void**。您也不能对此进行算术。

因此,这里的幼稚,糟糕的解决方案是将指针转换为int,然后进行简单的加法。这也不起作用,因为不能保证int能够保存指针的内容。应该使用uintptr_t代替int

最后,只有在编译器已将其中存储的内容视为int*类型的情况下,才可以通过int访问该内存块然后取消引用。如果不是,它将调用未定义的行为What is the strict aliasing rule?

摘要:这是一个非常有问题的代码,并且有很多更好的方法来实现它。