问题描述
template <class _Alloc>
class debug_alloc {
private:
enum {_S_extra = 8}; // Size of space used to store size. Note
// that this must be large enough to preserve
// alignment.
public:
static void* allocate(size_t __n)
{
char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra);
*(size_t*)__result = __n;
return __result + (int) _S_extra;
}
static void deallocate(void* __p,size_t __n)
{
char* __real_p = (char*)__p - (int) _S_extra;
assert(*(size_t*)__real_p == __n);
_Alloc::deallocate(__real_p,__n + (int) _S_extra);
}
static void* reallocate(void* __p,size_t __old_sz,size_t __new_sz)
{
char* __real_p = (char*)__p - (int) _S_extra;
assert(*(size_t*)__real_p == __old_sz);
char* __result = (char*)
_Alloc::reallocate(__real_p,__old_sz + (int) _S_extra,__new_sz + (int) _S_extra);
*(size_t*)__result = __new_sz;
return __result + (int) _S_extra;
}
};
这是调试模板。
我可以看到它确保分配的空间始终大于8个字节,并且我还可以看到它使用*(size_t*)__result = __n;
替换了从__result的地址开始的内容,但我对此感到非常困惑
为什么要分配空间然后用__n替换内容?
为什么然后返回__result + (int) _S_extra;
并定义char* __real_p = (char*)__p - (int) _S_extra;
?
请详细说明函数void* allocate(size_t __n)
和void deallocate(void* __p,size_t __n)
在内存中的工作方式。
链接到源代码:https://github.com/karottc/sgi-stl/blob/master/concept_checks.h
解决方法
此分配器在每个分配之前使用一个8字节的标头来记录其大小。通常将这样的元数据存储在实际分配旁边。即使标头包含一个4字节的整数,但8个字节仍可确保返回的指针与8个字节对齐,这是较大类型的常见要求。
从代码中可以看到,分配请求n + 8个字节(称为结果分配p),将大小存储在开头,然后返回p + 8。
取消分配和重新分配的指针为p + 8,因此必须先减去以返回到实际分配。