编写一个自定义malloc,它将信息存储在指针中

时间:2011-08-13 10:53:25

标签: garbage-collection memory-management malloc

我最近一直在阅读一系列自动内存管理技术,这些技术依赖于在分配器返回的指针中存储信息,即标题的少量位,例如区分指针或存储线程相关信息(请注意,我不是在谈论有限字段引用计数,只是不可变信息)。

我想玩这些技巧。现在,为了实现它们,我需要能够从我的分配器返回具有特定形状的指针。我想我可以用最轻的比特来玩,但这需要填充看起来非常耗费内存,所以我相信我应该玩最重的比特。但是,我不知道如何做到这一点。有没有办法让我,调用mallocmalloc_create_zone或一些相关的函数,并请求一个始终以给定位开头的指针?

谢谢大家!

1 个答案:

答案 0 :(得分:2)

您实际可以存储在指针中的信息量非常有限(通常每个指针有一位或两位)。每次取消引用指针的尝试都必须首先掩盖魔法信息。该技术通常称为tagging,BTW。

 #define TAG_MASK   0x3
 #define CONS_TAG   0x1
 #define STRING_TAG 0x2
 #define NUMBER_TAG 0x3

 typedef uintptr_t value_t; 
 typedef struct cons {
     value_t car;
     value_t cdr;
 } cons_t;

 value_t
 create_cons(value_t t1, value_t t2)
 {
     cons_t* pair = malloc(sizeof(cons_t));
     value_t addr = (value_t)pair;
     pair->car = t1;
     pair->cdr = t2;
     return addr | CONS_TAG;
 }

 value_t
 car_of_cons(value_t v)
 {
     if ((v % TAG_MASK) != CONS_TAG) error("wrong type of argument");
     return ((cons_t*) (v & ~TAG_MASK))->car;
 }

这种技术的一个优点是,您可以直接从指针本身推断出对象的类型。您不需要取消引用它(例如,为了读取特殊的type字段或类似字段)。许多使用此方案的语言实现也​​对“立即”数字和其他小值有一个特殊的标记组合,可以使用“指针”直接表示。

缺点是,可以存储的信息量非常有限。此外,如示例代码所示,您必须知道对对象的每次访问中的标记,并且需要在实际使用之前“取消”指针。

使用最低有效位来标记来自观察的词干,在大多数平台上,所有指向malloc内存的指针实际上都是在非字节边界上对齐(通常是8个字节),所以最少有效位始终为零。