ZEND_MM_SMALL_FREE_BUCKET宏,虽然鸟哥等人也有描述,可能是我愚笨,确实没有看懂,又自行一点点地扣了一下,记录如下:

struct _zend_mm_heap {

zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2]; // 指针的数组

};

#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \

(zend_mm_free_block*) ((char*)&heap->free_buckets[index * 2] + \

sizeof(zend_mm_free_block*) * 2 – \

sizeof(zend_mm_small_free_block))

如上图所示,首先,在为struct _zend_mm_heap * heap分配完内存之后,heap->free_buckets指向一块包含ZEND_MM_NUM_BUCKETS * 2个指针元素的数组。

假设使用index=0调用该宏,那么执行完(char*)&heap->free_buckets[index * 2]之后,指针指向free_bucket的第一个字节,且注意,已经被转换为(char*)了!

随后,当+sizeof(zend_mm_free_block*) * 2后,即向后偏移了两个pointer,在64位机上就是8*2=16个字节。这时,在我们的脑海里虚幻出来一个假的zend_mm_small_free_block,它以当前指针为结尾。并且,请注意zend_mm_small_free_block与zend_mm_free_block的区别如下图,不论debug宏等如何设置,它们前半段都是一样的

随后,再-sizeof(zend_mm_small_free_block)并显示转化为(zend_mm_free_block*)指针之后,返回值其实是指向一块偏移为负值的非法内存的。但那又怎样呢?只要我们不去访问非法区域就ok了啊!返回值仅会进行的操作就是取p->prev_free_block和next_free_block,而这两块确确实实是正确映射的!

Leave a Reply