堆的理解

参考hac师傅的博客和CTF-wiki自己总结一下。理解有误,请多指正。

堆块概念

堆为程序运行时可以由程序动态申请的线性内存区域,由低地址向高地址增长(栈为从高到低),在C语言中可以通过mallocfree进行堆块申请和释放操作。

堆块机制

堆分配中以chunk为单位,其中chunk的数据结构如下:

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;
};

prev_size:当前一个堆块为free状态时,存放前一个堆块的大小。在前一个堆块不处于空闲状态时,数据为前一个堆块中用户写入的数据,本字段不计入chunk的大小计算。
size:本堆块的大小,计算方法为size字段(32位为4|64位为8)+用户申请的大小+对齐,32位下对8对齐,64位下对16对齐。且chunk地址的偏移为相邻上一个chunk的地址+上一个chunk的size。在pwndbg中调试好像会加上一位PREV_INUSE
fb&bk:当chunk为free的状态时,分别指向chunk所在单向链表中的前一个chunk和后一个chunk。在被分配状态时,均用来存储数据,fb为存储数据的开始位置。
fb_nextsize&bk_nextsize:在被分配状态时也用来存储数据,在free状态时只在large bin中用到,目前没有用,等用到了再总结。

堆块分配机制

Bins

A bin is a list (doubly or singly linked list) of free (non-allocated) chunks.

bin为一个单向或者双向链表存放空闲的chunk,下一次分配时,若bin中有大小合适的chunk会直接分配出去。bin由存放其中的chunk大小分类为fastbinsmallbinlargebin
比较常用的是fastbin,在32位系统下fastbin主要存储0-80字节的chunk,在64位系统下存储0-160字节的chunk。
其中还有一个unsorted bin,是当small chunklarge chunkfree掉之后,不会直接进入smallbin或largebin,而是会先进入unsortedbin

arena

个人理解arena为chunk的存储组织形式,在arena的最上层始终为Top chunk,向下分出用户chunk,其中主线程中的arena为main arena。

top chunk

top chunk为arena的边界,当bin中无合适的chunk分配时,会将top chunk分出一部分进行分配。
当与top chunk相邻的chunk处于free状态时,该chunk不会进入bin中,而是会合并入top chunk。

你可能感兴趣的:(堆的理解)