0

当我阅读 SGI/STL 的源代码时,我注意到

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 字节,并且我还可以看到它通过 using 替换了从 __result 地址开始的内容,*(size_t*)__result = __n;但我真的很困惑这样做的目的。

为什么分配空间然后用 __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

4

1 回答 1

1

这个分配器在每个分配前使用一个 8 字节的标头来记录其大小。通常将这样的元数据存储在实际分配旁边。即使标头包含 4 字节的 int,8 字节确保返回的指针与 8 字节对齐,这是较大类型的常见要求。

从代码中可以看出,allocate 请求 n+8 个字节(调用结果分配 p),将大小存储在开头并返回 p+8。

释放和重新分配的指针是 p+8,所以必须先减去才能回到真正的分配。

于 2020-10-16T07:36:36.157 回答