malloc_chunk边界标记法和空间复用

22 篇文章 0 订阅

边界标记法

ptmalloc分配的空间统一用了malloc_chunk结构来管理,malloc_chunk的结构初看比较奇葩,看了注释,分析了一段时间的代码,发现这种边界标记的设计,在malloc_chunk虚拟地址都是彼此相邻的情况下,是十分高效的。

malloc_chunk结构:

/*
  This struct declaration is misleading (but accurate and necessary).
  It declares a "view" into memory allowing access to necessary
  fields at known offsets from a given base. See explanation below.
*/


struct malloc_chunk {


  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */


  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;


  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};


    首先我们要清楚,malloc_chunk都是虚拟地址相连的,这样我们需要知道一个chunk相邻chunk的地址。每个malloc_chunk都包括自身的size,又包括虚拟地址前面的那个malloc_chunk,这里不需要记录后面malloc_chunk的size,因为后面的首地址就是当前malloc_chunk的首地址+size,prev_size在前面的chunk如果是空闲的时候才是可用的。如果前面的chunk是正在被使用的,那么这个prev_size的空间则被前面的chunk所征用。如果当前chunk是使用中的,那么fd,bk,fd_nextsize,bk_nextsize,都是无效的,它们都是关于空闲链表的指针,那么这些指针的空间全部被认为是空闲空间。 ptmalloc中的注释画出了空闲malloc_chunk和已分配的malloc_chunk的结构。

空闲chunk的结构:

    上图中是空闲chunk的结构示意图,从图中可以看出当前malloc_chunk的指针是chunk指针,如果想得到地址相邻前面的指针,只需要chunk-prev_size即可。得到地址相邻后面的指针,chunk+size。其中fd,bk指针是bin中的空闲双向链表。这种通过prev_size可以使malloc_chunk的合并过程非常迅速。

    从代码中看下空闲chunk的合并过程,还是malloc_consolidate里面函数的片段:

//合并前面的
if (!prev_inuse(p))
{
    prevsize = p->prev_size;
    size += prevsize;
    p = chunk_at_offset(p, -((long) prevsize));
    unlink(p, bck, fwd);
}

//合并后面的
if (nextchunk != av->top) 
{
    nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
    if (!nextinuse)
    {
        size += nextsize;
        unlink(nextchunk, bck, fwd);
    }
}


    从代码中可以看出来,合并前面的malloc_chunk过程中,可以看到不用获得前面malloc_chunk的指针,合并的过程大概就是当前的chunk指针挪动到前面的位置,同时更新size,把chunk指针从相应的bin双向链表中干掉;从合并过程中可以看到,我们只是用到了prev_size,并没有用前面的chunk的指针,如果有前面chunk的指针,那么合并过程肯定还是需要这个chunk的size的。所以这里只用到prev_size加快合并的速度。向prev方向合并需要更新size和chunk指针,向next方向合并,只要更新size就行。


空间复用

    malloc_chunk来说size是必须的,标志了这个chunk的大小,来决定是否满足malloc的要求,那么对于空闲的malloc_chunk来说fd,bk,fd_nextsize,bk_nextsize是必须的,bin中的空闲双链表;对于非空闲的malloc_chunk来说,fd,bk,fd_nextsize,bk_nextsize是没有用的,所以这部分空间被作为了可用的空间。那么prev_size就比较复杂了,它的状态取决于虚拟地址相邻前面的chunk的状态,如果前面的chunk是使用状态,那么这个chunk的prev_size就没有意义了,也没有合并的必要了,所以就不需要知道前面chunk指针的位置了,所以这个变量的空间被前面的chunk征用了。

使用状态的chunk

    malloc请求的size,要加上结构体的数据大小才和malloc_chunk的size有可比性。

#define request2size(req) \
    (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? MINSIZE : \
     ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)

    从上面的宏可以看出实际请求的大小是req再加上size_t然后对齐,这里prev_size和size不是应该2*size_t么,但是还要计算上next chunk赠送的prev_size的size_t。


总结

从上面的分析可以看出malloc_chunk设计是巧妙的,prev_size字段可以通过它来找到地址相邻空闲的上一个chunk,使得合并空闲的chunk十分方便,同时如果当前chunk的前一个chunk是使用中的,prev_size的空间可以借给上一个chunk作为可用空间。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: malloc_consolidate(): invalid chunk size 的意思是 malloc_consolidate() 函数遇到了无效的块大小。这通常是由于程序试图释放一个无效的内存块或者是内存泄漏导致的。建议检查程序中的内存分配和释放操作,确保它们正确无误。 ### 回答2: malloc_consolidate()是一个在C语言中用于动态内存分配的函数。它负责维护堆的数据结构,以便更好地利用动态内存。但是,当出现"invalid chunk size"的错误时,说明该函数无正确处理堆中某个块的大小。 造成这个问题的原因可能是多种多样的。其中一种可能是在动态内存分配的过程中,出现了越界访问或缓冲区溢出等问题,导致了对某个块的尺寸记录的混乱或被篡改了。另外,也可能是别的原因导致malloc_consolidate()无正确将某个已经释放的块合并到后续的块中。这些都可能导致该函数所存在的问题。 解决这个问题的方,需要我们针对具体的情况进行调查和分析。典型的做是通过调试程序的方式,利用一些工具来检查内存分配的情况,找到出现问题的地方以及对应的内存分配操作,进而对其进行修正和改善。例如,可以使用Valgrind的memcheck工具来检查进程中的内存错误和泄漏问题,或使用gdb进行调试,定位出问题的具体原因。 总而言之,解决malloc_consolidate()出现"invalid chunk size"错误,需要我们深入理解内存分配的原理和过程,确定问题所在,然后针对性地进行修正和优化。这有可能涉及到程序整体结构的调整和代码的重构,需要我们有足够的耐心和技术能力来完成。 ### 回答3: malloc_consolidate()是一个C语言中的函数,用于堆内存的管理,具体作用是整理释放内存块后的未连续的内存空间,将它们合并成更大的内存块,提高内存的利用率。 但是,在使用malloc_consolidate()函数时,有可能会出现“invalid chunk size”的错误提示。这个错误通常是由于程序员使用了不正确的内存地址或尺寸,导致函数无正确运行。 具体来说,这个错误可能有以下几种原因: 1)堆内存的指针地址不合或者已经被释放 2)在调用malloc()等内存分配函数时,传递了不合的尺寸参数(比如负数) 3)堆内存存在内存越界或数据损坏等问题。 如果程序员遇到了“invalid chunk size”的错误提示,可以尝试使用调试工具进行调试,查看具体的错误代码位置和堆内存的状态,以找到问题所在。另外,建议在程序开发时,对内存分配和释放等操作进行更加严格的验证和处理,以避免出现不必要的错误。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值