这是一个本人学习 csapp 的 learning 库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3.0 KiB

关于示例代码的理解

环境

  • mem_init 中可以看出整个分配器是在一大段已经分配好的连续的内存中进行的
  • 同样每次 mem_sbrk 进行扩展时也是连续扩展,模拟堆的向上增长

对齐

  • 标准 malloc 也是八字节对齐,所以可以满足强制八字节对齐的要求
  • 返回的内存应为有效载荷部分,如果每个块加上头部和脚部,为了满足对齐要求,须在开头空出四字节的位置
  • 也意味着空闲块最小为八字节大小,有效载荷也应八字节对齐,已分配块最小十六字节

测试

  • handout 里的测试用例偏少,从网上找到了更为详尽的 traces 测试用例来测试

version 1

规则与注意

理解逻辑后,接下来将实现自己的版本

  • 为方便理解,定义了两个类型别名
    typedef unsigned int word;
    typedef char byte;
    
  • 不同于示例代码用序言块和尾块标记,本人仅用两个指针标记头尾,来提高内存利用率
    // mark the front and tail pos
    void *front_p = NULL;
    void *tail_p = NULL;
    
    • 但会增加代码的复杂度,需着重维护
    • 同时还应注意若 bp == front_pPREV(bp) 内的值无效,tail_p 同理
  • 为保持一致性,向辅助函数内传入的 size 均应在传入之前对齐,均不包含头尾部大小
  • 仅在内部碎片大于等于十六字节时才进行切割
  • 其他部分与示例大同小异

bug 与 debug

  • #debug对于 segmentation fault 使用 gdb 获取头尾块的 size 发现尾部异常值 0xcdcdcd,在代码中使用 print 跟踪 trail_p 变量,发现在__coalesce_next处没有及时更新
  • #bug1 若记录的 size 是有效载荷的 size,合并和分割时应注意增减 DSIZE
  • #bug2 每次合并都需要判断 tail_p 是否改变,特别是 __coalesce_next 的情况

方法与得分

  • 隐式空闲链表,首次适配,立即合并
Results for mm malloc:
trace  valid  util     ops      secs  Kops
 0       yes   99%    5694  0.007579   751
 1       yes  100%    5848  0.006639   881
 2       yes   99%    6648  0.010560   630
 3       yes  100%    5380  0.008016   671
 4       yes  100%   14400  0.000102140762
 5       yes   92%    4800  0.006677   719
 6       yes   92%    4800  0.005988   802
 7       yes   55%   12000  0.141468    85
 8       yes   51%   24000  0.274197    88
 9       yes   33%   14401  0.128358   112
10       yes   50%   14401  0.002138  6734
Total          79%  112372  0.591722   190

Perf index = 47 (util) + 13 (thru) = 60/100

Version 1.1

针对 realloc 的优化 v1

  • new_size <= old_size 则不分配而是切割
  • 若下一块未分配且总和大于 new_size 则合并
  • 若合并后内部碎片过大则仍需分割
  • 提高六分,但判断过多,且考虑不全

针对 realloc 的优化 v2

  • 评估前后空闲块的总大小,若足够,则合并
  • 合并不会破坏数据,合并后复制数据,再根据需要分割

2022.12.29 ~ 2022.12.30