## 关于示例代码的理解
#### 环境
* 从 `mem_init` 中可以看出整个分配器是在一大段已经分配好的连续的内存中进行的
* 同样每次 `mem_sbrk` 进行扩展时也是连续扩展，模拟堆的向上增长
#### 对齐
* 标准 `malloc` 也是八字节对齐，所以可以满足强制八字节对齐的要求
* 返回的内存应为有效载荷部分，如果每个块加上头部和脚部，为了满足对齐要求，须在开头空出四字节的位置
* 也意味着空闲块最小为八字节大小，有效载荷也应八字节对齐，已分配块最小十六字节
#### 测试
* handout 里的测试用例偏少，从网上找到了更为详尽的 `traces` 测试用例来测试
## version 1
#### 规则与注意
理解逻辑后，接下来将实现自己的版本
* 为方便理解，定义了两个类型别名
    ```c
    typedef unsigned int word;
    typedef char byte;
    ```
* 不同于示例代码用序言块和尾块标记，本人仅用两个指针标记头尾，来提高内存利用率
    ```c
    // mark the front and tail pos
    void *front_p = NULL;
    void *tail_p = NULL;
    ```
  * 但会增加代码的复杂度，需着重维护
  * 同时还应注意若 `bp == front_p` 则 `PREV(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` 的情况
#### 方法与得分
* 隐式空闲链表，首次适配，立即合并
```c
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