Tcmalloc源码简单分析(7)

下面我们开始分析三个malloc函数分别是DevMemSysAllocatorMmapSysAllocator,以及SbrkSysAllocator./src/system-alloc.cc)。

首先分析SbrkSysAllocator./src/system-alloc.cc

void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size,

                              size_t alignment) {

#ifndef HAVE_SBRK

  failed_ = true;

  return NULL;

#else

  // Check if we should use sbrk allocation.

  // FLAGS_malloc_skip_sbrk starts out as false (its uninitialized

  // state) and eventually gets initialized to the specified value.  Note

  // that this code runs for a while before the flags are initialized.

  // That means that even if this flag is set to true, some (initial)

  // memory will be allocated with sbrk before the flag takes effect.

  if (FLAGS_malloc_skip_sbrk) {

    return NULL;

  }

//首先判断内存的分配是否采用sbrk,如果FLAGS_malloc_skip_sbrk设置为true那么代表着不适用sbrk,则直接返回NULL,代表分配失败。

  // sbrk will release memory if passed a negative number, so we do

  // a strict check here

  if (static_cast<ptrdiff_t>(size + alignment) < 0) return NULL;

//由于sbrk可以通过传入负值动态缩减heap顶部,因此在分配函数中把这种情况先排除。

  // This doesn't overflow because TCMalloc_SystemAlloc has already

  // tested for overflow at the alignment boundary.

  size = ((size + alignment - 1) / alignment) * alignment;

//通过alignment对齐,将非对齐的size转换为对齐

  // "actual_size" indicates that the bytes from the returned pointer

  // p up to and including (p + actual_size - 1) have been allocated.

  if (actual_size) {

    *actual_size = size;

  }

 

  // Check that we we're not asking for so much more memory that we'd

  // wrap around the end of the virtual address space.  (This seems

  // like something sbrk() should check for us, and indeed opensolaris

  // does, but glibc does not:

  //    http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/sys/sbrk.c?a=true

  //    http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/libc/misc/sbrk.c?rev=1.1.2.1&content-type=text/plain&cvsroot=glibc

  // Without this check, sbrk may succeed when it ought to fail.)

  if (reinterpret_cast<intptr_t>(sbrk(0)) + size < size) {

    failed_ = true;

    return NULL;

  }//判断我们申请的size有没有超过进程空间能够提供的最大值

 

  void* result = sbrk(size);

  if (result == reinterpret_cast<void*>(-1)) {

    failed_ = true;

    return NULL;

  }

//利用sbrk申请size大小的空间

  // Is it aligned?

  uintptr_t ptr = reinterpret_cast<uintptr_t>(result);

  if ((ptr & (alignment-1)) == 0)  return result;

//如果申请成功,那么判断是否符合对齐要求,如果对齐,那么返回结果

  // Try to get more memory for alignment

  size_t extra = alignment - (ptr & (alignment-1));

  //如果没有对齐,那么判断还缺少多少size可以对齐,

  void* r2 = sbrk(extra);

 //申请需要的size进行对齐

  if (reinterpret_cast<uintptr_t>(r2) == (ptr + size)) {

    // Contiguous with previous result

    return reinterpret_cast<void*>(ptr + extra);

//符合对齐要求,那么返回结果

  }

 

  // Give up and ask for "size + alignment - 1" bytes so

  // that we can find an aligned region within it.

  result = sbrk(size + alignment - 1);//否者将不管对齐与否,申请一个比size大的空间,至少保证在这个空间内可以找到一块对齐的空间,这里面应该分为两种情况,第一种情况是以上分配都是失败的,第二种情况是分配没有失败,只是没有找到相应的对齐

  if (result == reinterpret_cast<void*>(-1)) {

    failed_ = true;

    return NULL;

  }

  ptr = reinterpret_cast<uintptr_t>(result);

  if ((ptr & (alignment-1)) != 0) {

    ptr += alignment - (ptr & (alignment-1));

         //保证ptr顶部对齐

  }

  return reinterpret_cast<void*>(ptr);

#endif  // HAVE_SBRK

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值