本文为USTC SSE CSAPP 2020 Fall实验三的记录,仅供参考

PPT链接在这里:Lab 5.pptx  代码在这里 mm2.c mm3.c

版本一代码如下(无注释  注释请看版本二):

/** mm-naive.c - The fastest, least memory-efficient malloc package.* * In this naive approach, a block is allocated by simply incrementing* the brk pointer.  A block is pure payload. There are no headers or* footers.  Blocks are never coalesced or reused. Realloc is* implemented directly using mm_malloc and mm_free.** NOTE TO STUDENTS: Replace this header comment with your own header* comment that gives a high level description of your solution.*/
#include "memlib.h"
#include "stdio.h"
#include "string.h"
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>#include "mm.h"
#include "memlib.h"/********************************************************** NOTE TO STUDENTS: Before you do anything else, please* provide your team information in the following struct.********************************************************/
team_t team = {/* Team name */"123456",/* First member's full name */"xxx xxx",/* First member's email address */"xxxx@mail.ustc.edu.cn",/* Second member's full name (leave blank if none) */"",/* Second member's email address (leave blank if none) */""
};/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8// 注释请参照 mm3.c/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & (~(ALIGNMENT-1)))#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
#define base_type size_t
#define base_pt base_type*
#define BASE_TYPE(e) ((base_type)e)
#define BASE_PT(e) ((base_pt)e)
#define BASE_TYPE_SIZE (ALIGN(sizeof(base_type)))#define INITED ~0#define OVHD_PREV_IDX -3
#define OVHD_NEXT_IDX -2
#define OVHD_SIZE_IDX -1
#define HD_INIT_IDX 0
#define FB_LIST_NUM 9
#define HD_N (FB_LIST_NUM + 1)
#define OVHD_N 3
#define HD_SIZE (BASE_TYPE_SIZE * HD_N)
#define OVHD_SIZE (BASE_TYPE_SIZE * OVHD_N)
#define TAIL_SIZE BASE_TYPE_SIZE
#define OV_SIZE (ALIGN(OVHD_SIZE + TAIL_SIZE))#define inc_n_byte(p, n) ((base_pt)((((char*)(p)) + n)))
#define HEAP_START_PT (inc_n_byte(mem_heap_lo(), HD_SIZE))#define calc_blcok_total_size(alloc_size) (OVHD_SIZE + ALIGN(alloc_size) + TAIL_SIZE)#define BLOCK_USED 0
#define BLOCK_FREE 1
#define BLOCK_FLAG_BITS 1
#define BLOCK_FLAG_MASK ((1 << BLOCK_FLAG_BITS) - 1)#define calc_size_val(size, v) ((size << BLOCK_FLAG_BITS) | v)#define m_read(p, idx) (((base_pt)(p))[((base_type)(idx))])
#define m_write(p, idx, v) (m_read(p, idx) = ((base_type)v))#define hd_read(idx) (m_read(mem_heap_lo(), idx))
#define hd_write(idx, v) (m_write(mem_heap_lo(), idx, v))#define hd_inited (m_read(mem_heap_lo(), HD_INIT_IDX))#define set_hd_inited() (m_write(mem_heap_lo(), HD_INIT_IDX, INITED))#define block_flag(p) ((m_read(p, OVHD_SIZE_IDX)) & BLOCK_FLAG_MASK)
#define block_size(p) ((m_read(p, OVHD_SIZE_IDX)) >> BLOCK_FLAG_BITS)
#define block_last(p) (inc_n_byte(p, ((block_size(p)) - (OV_SIZE))))
#define block_next(p) (BASE_PT(m_read(p, OVHD_NEXT_IDX)))
#define block_prev(p) (BASE_PT(m_read(p, OVHD_PREV_IDX)))
#define block_content_pt(p) (inc_n_byte(p, OVHD_SIZE))#define is_block_used(p) ((block_flag(p)) == (BLOCK_USED))
#define is_block_free(p) ((block_flag(p)) != (BLOCK_USED))#define set_block_hd_size(p, v) (m_write(p, OVHD_SIZE_IDX, v))
#define set_block_td_size(p, v) (m_write(block_last(p), 0, v))
#define set_block_next(p, v) (m_write(p, OVHD_NEXT_IDX, v))
#define set_block_prev(p, v) (m_write(p, OVHD_PREV_IDX, v))#define REMIAN_SIZE (ALIGN(sizeof(base_type) * 3))
#define EXTRA_SAPCE (ALIGN(REMIAN_SIZE + OV_SIZE))#define print(m_type) (printf("sizeof(" #m_type "): %d\n", sizeof(m_type)))#define DEBUG_MODE 0void set_block_size(base_pt block, base_type total_size, base_type block_flag) {base_type size_val = calc_size_val(total_size, block_flag);set_block_hd_size(block, size_val);set_block_td_size(block, size_val);
}#define set_block_used(block, total_size) (set_block_size(block, total_size, BLOCK_USED))
#define set_block_free(block, total_size) (set_block_size(block, total_size, BLOCK_FREE))
#define mark_block_used(block)  (set_block_used(block, block_size(block)))
#define mark_block_free(block)  (set_block_free(block, block_size(block)))void px(void* p, int x) {for (int i = 0; i < x; i++) {printf("i:%d, addr: 0x%x, content:0x%x\n", i, &m_read(p, i), m_read(p, i));}
}void print_type_info() {printf("\n");print(char*);print(void*);print(base_pt);print(base_type);print(int);printf("\n");
}base_type get_list_idx(base_type total_size) {base_type idx[FB_LIST_NUM - 1] = {48, 64, 128, 256, 512, 1024, 2072, 4104};base_type i = 0;for (; i < FB_LIST_NUM - 1; i++)if (total_size <= idx[i])break;return i + 1;
}void insert_into_free_list_head(base_pt block) {base_type size = block_size(block);base_type list_idx = get_list_idx(size);// if (DEBUG_MODE)//     printf("insert block(addr:%p size:%d) into list %d\n", block, size, list_idx);set_block_free(block, size);       set_block_prev(block, NULL);set_block_next(block, NULL);base_pt head = BASE_PT(hd_read(list_idx));if (head == NULL) {hd_write(list_idx, block);}else {base_pt old_head = head;hd_write(list_idx, block);set_block_next(block, old_head);if (old_head)set_block_prev(old_head, block);}
}void print_list() {// printf("\n");for (base_type i = 1; i <= FB_LIST_NUM; i++) {printf("list: idx=%d, element:", i);base_pt pt = hd_read(i);while(pt != NULL) {printf("[%p(%d:%d)]", pt, block_size(pt), block_flag(pt));pt = block_next(pt);if (pt)printf(" -> ");}printf("\n");}printf("\n");
}base_pt search_free_list(base_type total_size) {base_type list_idx = get_list_idx(total_size);for (base_type idx = list_idx; idx <= FB_LIST_NUM; idx++) {base_pt pt = BASE_PT(hd_read(idx));while (pt && (block_size(pt) < total_size))pt = block_next(pt);if (pt) {if (DEBUG_MODE)printf("found free block(addr:%p, size:%d)\n", pt, block_size(pt));return pt;}}if (DEBUG_MODE)printf("found no free block\n");return NULL;
}void remove_from_free_list(base_pt block) {base_type list_idx = get_list_idx(block_size(block));if (!block_prev(block))hd_write(list_idx, block_next(block));elseset_block_next(block_prev(block), block_next(block));if (block_next(block))set_block_prev(block_next(block), block_prev(block));set_block_prev(block, NULL);set_block_next(block, NULL);mark_block_used(block);return block;
}base_pt split_block(base_pt block, base_type total_size) {base_type size = block_size(block);if (is_block_used(block)) {printf("split block error: try to split an used block\n");return NULL;}if (size < total_size) {printf("split block error: try to split block into bigger blocks.\n");return NULL;}else {remove_from_free_list(block);if (size >= (total_size + EXTRA_SAPCE)) {base_pt new_block = inc_n_byte(block, total_size);base_pt list_idx = get_list_idx(size);set_block_used(block, total_size);set_block_used(new_block, size - total_size);if (DEBUG_MODE)printf("split free block(addr:%p, size:%d) into ret block(addr:%p, size:%d) and ", block, size, block, block_size(block));if (DEBUG_MODE)printf("new block(addr:%p, size:%d)\n", new_block, block_size(new_block));insert_into_free_list_head(new_block);}return block;}
}void* true_malloc(base_type total_size) {base_pt *p = BASE_PT(mem_sbrk(total_size));// printf("info: true malloc has got a new block with addr: %p, size: %llu\n", p,  total_size);if (p == -1)return NULL;p = block_content_pt(p);set_block_next(p, NULL);set_block_prev(p, NULL);set_block_used(p, total_size);return (void*)p;
}int mm_init (void) {// print_type_info();base_type r = BASE_TYPE(mem_sbrk(HD_SIZE));if (r == -1)return -1;set_hd_inited();for (base_type i = 1; i <= FB_LIST_NUM; i++)hd_write(i, NULL);// printf("low: 0x%x, high:0x%x\n", mem_heap_lo(), mem_heap_hi());// px(mem_heap_lo(), 5);return 0;
}void * mm_malloc (size_t size) {if (!size)  return NULL;if (hd_inited != INITED) {printf("error: try to call malloc before inited.\n");return NULL;}base_type total_size = calc_blcok_total_size(size);base_pt pt = search_free_list(total_size);if (pt == NULL) {void *r =  true_malloc(total_size);if (DEBUG_MODE) {printf("malloc: request size: %d, allocated addr: %p, size: %d\n", size, r, block_size(r));print_list();}return r;}else {void *r = split_block(pt, total_size);if (DEBUG_MODE) {printf("malloc: request size: %d, allocated addr: %p, size: %d\n", size, r, block_size(r));print_list();}return r;}
}void mm_free(void *ptr) {if (hd_inited != INITED) {printf("free rror: try to call free before inited.\n");return;}base_pt pt = BASE_PT(ptr);if (is_block_free(pt)) {printf("free error: try to free a free block with addr: %p\n", pt);return;}if (DEBUG_MODE)printf("free: try to free a block with addr:%p, size:%d\n", ptr, block_size(ptr));base_type size = block_size(pt);if (DEBUG_MODE)printf("-----------------free analysis for block(addr:%p, size:%d)------------------------\n", pt, size);base_type prev_block_size_val_pt = inc_n_byte(pt, -(OVHD_SIZE + BASE_TYPE_SIZE));if (DEBUG_MODE)printf("prev: size_val_pt:%p heap_start:%p\n", prev_block_size_val_pt, HEAP_START_PT);if (prev_block_size_val_pt > HEAP_START_PT) {base_type prev_block_size_val = m_read(pt, -(OVHD_N + 1));if (DEBUG_MODE)printf("prev_block_size_val:0x%x, flag:%x\n", prev_block_size_val, prev_block_size_val & BLOCK_FLAG_MASK);if ((prev_block_size_val & BLOCK_FLAG_MASK) != BLOCK_USED) {base_type prev_block_size = (prev_block_size_val >> BLOCK_FLAG_BITS);base_pt prev_block = inc_n_byte(pt, -prev_block_size);if (DEBUG_MODE)printf("merge current block(addr:%p size:%d) and prev block(addr:%p size:%d) into ", pt, size, prev_block, prev_block_size);remove_from_free_list(prev_block);size += prev_block_size;pt = prev_block;set_block_size(pt, size, BLOCK_USED);if (DEBUG_MODE)printf("new block(addr:%p, size:%d)\n", pt, block_size(pt));}}base_pt next_block = inc_n_byte(pt, size);if (DEBUG_MODE)printf("next: block_pt:%p heap_hi:%p\n", next_block, mem_heap_hi());if (next_block < mem_heap_hi()) {base_type next_block_size_val = m_read(next_block, OVHD_SIZE_IDX);if (DEBUG_MODE)printf("next_block_size_val:0x%x flag:%x\n", next_block_size_val, next_block_size_val & BLOCK_FLAG_MASK);if ((next_block_size_val & BLOCK_FLAG_MASK) != BLOCK_USED) {base_type next_block_size = (next_block_size_val >> BLOCK_FLAG_BITS);if (DEBUG_MODE)printf("merge current block(addr:%p size:%d) and next block(addr:%p size:%d) into", pt, size, next_block, next_block_size);remove_from_free_list(next_block);set_block_size(pt, size + next_block_size, BLOCK_USED);if (DEBUG_MODE)printf("new block(addr:%p, size:%d)\n", pt, block_size(pt));}}if (DEBUG_MODE)printf("----------------------------------free analysis end--------------------------------------\n", pt, size);insert_into_free_list_head(pt);if (DEBUG_MODE)print_list();
}void *mm_realloc(void *ptr, size_t size) {if (hd_inited != INITED) {printf("error: try to call realloc before inited.\n");return NULL;}if (DEBUG_MODE)printf("realloc: try to realloc a block with addr:%p, size:%d\n", ptr, size);if (!ptr)   return mm_malloc(size);if (!size)  {mm_free(ptr);return NULL;}base_type blockSize = block_size(ptr);base_type adjusted_size = calc_blcok_total_size(size);if (adjusted_size <= blockSize) {if (DEBUG_MODE)print_list();return ptr;}else {base_pt new_ptr = mm_malloc(size);if (!new_ptr)   return NULL;memcpy(new_ptr, ptr, blockSize - OVHD_SIZE);mm_free(ptr);if (DEBUG_MODE)print_list();return new_ptr;}
}

版本二代码如下:

/** mm-naive.c - The fastest, least memory-efficient malloc package.* * In this naive approach, a block is allocated by simply incrementing* the brk pointer.  A block is pure payload. There are no headers or* footers.  Blocks are never coalesced or reused. Realloc is* implemented directly using mm_malloc and mm_free.** NOTE TO STUDENTS: Replace this header comment with your own header* comment that gives a high level description of your solution.*/
#include "memlib.h"
#include "stdio.h"
#include "string.h"
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>#include "mm.h"
#include "memlib.h"/********************************************************** NOTE TO STUDENTS: Before you do anything else, please* provide your team information in the following struct.********************************************************/
team_t team = {/* Team name */"123456",/* First member's full name */"xxx xxx",/* First member's email address */"xxxx@mail.ustc.edu.cn",/* Second member's full name (leave blank if none) */"",/* Second member's email address (leave blank if none) */""
};/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & (~(ALIGNMENT-1)))// 一些常用的type和他们的size
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
#define base_type size_t
#define base_pt base_type*
#define BASE_TYPE(e) ((base_type)e)
#define BASE_PT(e) ((base_pt)e)
#define BASE_TYPE_SIZE (ALIGN(sizeof(base_type)))// 堆头部初始化标志
#define INITED ~0// 块头部的值的下标  相对块的内容的第一个字节的指针
#define OVHD_PREV_IDX -3
#define OVHD_NEXT_IDX -2
#define OVHD_SIZE_IDX -1
// 堆头部得下标
#define HD_INIT_IDX 0
#define FB_LIST_NUM 9
// 堆头部的值的个数v
#define HD_N (FB_LIST_NUM + 1)
// 块头部的值的个数  OV为Overhead
#define OVHD_N 3
// 堆头部的大小
#define HD_SIZE (BASE_TYPE_SIZE * HD_N)
// 块头部的大小
#define OVHD_SIZE (BASE_TYPE_SIZE * OVHD_N)
// 块尾部的大小
#define TAIL_SIZE BASE_TYPE_SIZE
// 一个块头部加尾部的大小
#define OV_SIZE (ALIGN(OVHD_SIZE + TAIL_SIZE))// 将一个指针前进n个字节,n为负数则为后退
#define inc_n_byte(p, n) ((base_pt)((((char*)(p)) + n)))
// 堆上非堆头部的最小的地址
#define HEAP_START_PT (inc_n_byte(mem_heap_lo(), HD_SIZE))// 给定块内容的大小,计算整个块最小的size
#define calc_blcok_total_size(alloc_size) (OVHD_SIZE + ALIGN(alloc_size) + TAIL_SIZE)// 用于块的标志位 0为已分配 1为空闲块
#define BLOCK_USED 0
#define BLOCK_FREE 1
#define BLOCK_FLAG_BITS 1
#define BLOCK_FLAG_MASK ((1 << BLOCK_FLAG_BITS) - 1)// 用size和flag构造出存储在块size部分的值
#define calc_size_val(size, flag) ((size << BLOCK_FLAG_BITS) | flag)// 将指针p看成base_pt类型 读取p[idx] 和 写入 p[idx] = v
#define m_read(p, idx) (((base_pt)(p))[((base_type)(idx))])
#define m_write(p, idx, v) (m_read(p, idx) = ((base_type)v))// 读写堆头部的数据结构
#define hd_read(idx) (m_read(mem_heap_lo(), idx))
#define hd_write(idx, v) (m_write(mem_heap_lo(), idx, v))// 读取堆头部是否初始化的信息
#define hd_inited (m_read(mem_heap_lo(), HD_INIT_IDX))// 设置堆头部已经初始化
#define set_hd_inited() (m_write(mem_heap_lo(), HD_INIT_IDX, INITED))// p为看成指向一个块的内容部分的第一个字节的指针,读取这个块的标志位,大小,next指针,prev指针,整个块的最后一个字节
#define block_flag(p) ((m_read(p, OVHD_SIZE_IDX)) & BLOCK_FLAG_MASK)
#define block_size(p) ((m_read(p, OVHD_SIZE_IDX)) >> BLOCK_FLAG_BITS)
#define block_next(p) (BASE_PT(m_read(p, OVHD_NEXT_IDX)))
#define block_prev(p) (BASE_PT(m_read(p, OVHD_PREV_IDX)))
#define block_last(p) (inc_n_byte(p, ((block_size(p)) - (OV_SIZE))))
// p为指向一个块的第一个字节的指针,计算得到指向这个块的内容部分的第一个字节的指针
#define block_content_pt(p) (inc_n_byte(p, OVHD_SIZE))// v为块的size1部分的内容,看是否为空闲块
#define is_free(v)  (((v) & BLOCK_FLAG_BITS) != BLOCK_USED)
// p为看成指向一个块的内容部分的第一个字节的指针,看这个块是空闲块还是已分配块
#define is_block_used(p) ((block_flag(p)) == (BLOCK_USED))
#define is_block_free(p) ((block_flag(p)) != (BLOCK_USED))// p为看成指向一个块的内容部分的第一个字节的指针,设置头部的size部分,尾部的size部分,next指针,prev指针
#define set_block_hd_size(p, v) (m_write(p, OVHD_SIZE_IDX, v))
#define set_block_td_size(p, v) (m_write(block_last(p), 0, v))
#define set_block_next(p, v) (m_write(p, OVHD_NEXT_IDX, v))
#define set_block_prev(p, v) (m_write(p, OVHD_PREV_IDX, v))// 用于在分裂空闲块时,如剩下部分小于这个值,就不再拆开块
#define REMIAN_SIZE (ALIGN(sizeof(base_type) * 3))
#define EXTRA_SAPCE (ALIGN(REMIAN_SIZE + OV_SIZE))// 用于调试 打印各种type的大小
#define print(m_type) (printf("sizeof(" #m_type "): %d\n", sizeof(m_type)))// 是否是调试模式
#define DEBUG_MODE 0// 给定一个指向一个块的内容部分的第一个字节的指针,设置其size部分的值,包括头部和尾部
void set_block_size(base_pt block, base_type total_size, base_type block_flag) {base_type size_val = calc_size_val(total_size, block_flag);set_block_hd_size(block, size_val);set_block_td_size(block, size_val);
}// 同上,只是不用再填 block_flag
#define set_block_used(block, total_size) (set_block_size(block, total_size, BLOCK_USED))
#define set_block_free(block, total_size) (set_block_size(block, total_size, BLOCK_FREE))// 功能同上 只修改flag 不改变块大小
#define mark_block_used(block)  (set_block_used(block, block_size(block)))
#define mark_block_free(block)  (set_block_free(block, block_size(block)))void px(void* p, int x) {for (int i = 0; i < x; i++) {printf("i:%d, addr: 0x%x, content:0x%x\n", i, &m_read(p, i), m_read(p, i));}
}void print_type_info() {printf("\n");print(char*);print(void*);print(base_pt);print(base_type);print(int);printf("\n");
}// 给定整个块的大小,返回其应该在的链表头指针在堆头部的下标
base_type get_list_idx(base_type total_size) {base_type idx[FB_LIST_NUM - 1] = {48, 64, 128, 256, 512, 1024, 2072, 4104};base_type i = 0;for (; i < FB_LIST_NUM - 1; i++)if (total_size <= idx[i])break;return i + 1;
}// 将一个块插入空闲链表的头部
void insert_into_free_list_head(base_pt block) {base_type size = block_size(block);base_type list_idx = get_list_idx(size);// if (DEBUG_MODE)//     printf("insert block(addr:%p size:%d) into list %d\n", block, size, list_idx);set_block_free(block, size);       set_block_prev(block, NULL);set_block_next(block, NULL);base_pt head = BASE_PT(hd_read(list_idx));if (head == NULL) {hd_write(list_idx, block);}else {base_pt old_head = head;hd_write(list_idx, block);set_block_next(block, old_head);if (old_head)set_block_prev(old_head, block);}
}// 调试用的函数  用于打印出所有的空闲链表
void print_list() {// printf("\n");for (base_type i = 1; i <= FB_LIST_NUM; i++) {printf("list: idx=%d, element:", i);base_pt pt = hd_read(i);while(pt != NULL) {printf("[%p(%d:%d)]", pt, block_size(pt), block_flag(pt));pt = block_next(pt);if (pt)printf(" -> ");}printf("\n");}printf("\n");
}// 在所有空闲链表中查找>=total_size的空闲块,返回块指针
base_pt search_free_list(base_type total_size) {base_type list_idx = get_list_idx(total_size);// 先计算出起始要找的链表的下标,这个链表如果没找到,就再到下一个链表继续找for (base_type idx = list_idx; idx <= FB_LIST_NUM; idx++) {base_pt pt = BASE_PT(hd_read(idx));while (pt && (block_size(pt) < total_size))pt = block_next(pt);if (pt) {if (DEBUG_MODE)printf("found free block(addr:%p, size:%d)\n", pt, block_size(pt));return pt;}}if (DEBUG_MODE)printf("found no free block\n");return NULL;
}// 将一个块从空闲链表中移除
void remove_from_free_list(base_pt block) {base_type list_idx = get_list_idx(block_size(block));if (!block_prev(block))hd_write(list_idx, block_next(block));elseset_block_next(block_prev(block), block_next(block));if (block_next(block))set_block_prev(block_next(block), block_prev(block));set_block_prev(block, NULL);set_block_next(block, NULL);mark_block_used(block);return block;
}// 空闲块太大,将一个空闲块进行分裂
base_pt split_block(base_pt block, base_type total_size) {base_type size = block_size(block);if (is_block_used(block)) {printf("split block error: try to split an used block\n");return NULL;}if (size < total_size) {printf("split block error: try to split block into bigger blocks.\n");return NULL;}else {remove_from_free_list(block);// 剩下部分比较多,就把剩下部分变成一个新的空闲块插入链表// 剩下部分不多就把整个块都分配出去if (size >= (total_size + EXTRA_SAPCE)) {base_pt new_block = inc_n_byte(block, total_size);set_block_used(block, total_size);set_block_used(new_block, size - total_size);if (DEBUG_MODE)printf("split free block(addr:%p, size:%d) into ret block(addr:%p, size:%d) and ", block, size, block, block_size(block));if (DEBUG_MODE)printf("new block(addr:%p, size:%d)\n", new_block, block_size(new_block));insert_into_free_list_head(new_block);}return block;}
}// 真正向系统要求分配一个大小为total_size的块
void* true_malloc(base_type total_size) {base_pt *p = BASE_PT(mem_sbrk(total_size));// printf("info: true malloc has got a new block with addr: %p, size: %llu\n", p,  total_size);if (p == -1)return NULL;p = block_content_pt(p);set_block_next(p, NULL);set_block_prev(p, NULL);set_block_used(p, total_size);return (void*)p;
}// 将一个块与其前后的空闲块进行合并
base_pt merge_prev_next_block(base_pt ptr) {base_pt pt = BASE_PT(ptr);base_type size = block_size(pt);if (DEBUG_MODE)printf("-----------------free analysis for block(addr:%p, size:%d)------------------------\n", pt, size);// 指向前一个块的尾部的size部分的指针base_type prev_block_size_val_pt = inc_n_byte(pt, -(OVHD_SIZE + BASE_TYPE_SIZE));if (DEBUG_MODE)printf("prev: size_val_pt:%p heap_start:%p\n", prev_block_size_val_pt, HEAP_START_PT);// 指向前一个块的尾部的size部分的指针 不能小于 堆真正开始处的地址if (prev_block_size_val_pt > HEAP_START_PT) {// 解析处前一个块的size部分的值 由size和flag构成base_type prev_block_size_val = m_read(pt, -(OVHD_N + 1));if (DEBUG_MODE)printf("prev_block_size_val:0x%x, flag:%x\n", prev_block_size_val, prev_block_size_val & BLOCK_FLAG_MASK);// 如果前一个块为空闲块if (is_free(prev_block_size_val)) {base_type prev_block_size = (prev_block_size_val >> BLOCK_FLAG_BITS);base_pt prev_block = inc_n_byte(pt, -prev_block_size);if (DEBUG_MODE)printf("merge current block(addr:%p size:%d) and prev block(addr:%p size:%d) into ", pt, size, prev_block, prev_block_size);remove_from_free_list(prev_block);size += prev_block_size;pt = prev_block;set_block_size(pt, size, BLOCK_USED);if (DEBUG_MODE)printf("new block(addr:%p, size:%d)\n", pt, block_size(pt));}}// 指向下一个块的内容部分的第一个字节的指针base_pt next_block = inc_n_byte(pt, size);if (DEBUG_MODE)printf("next: block_pt:%p heap_hi:%p\n", next_block, mem_heap_hi());// 指向下一个块的内容部分的第一个字节的指针 不能超出堆的最大范围if (next_block < mem_heap_hi()) {// 找出下一个块的size部分的值 包括size和flagbase_type next_block_size_val = m_read(next_block, OVHD_SIZE_IDX);if (DEBUG_MODE)printf("next_block_size_val:0x%x flag:%x\n", next_block_size_val, next_block_size_val & BLOCK_FLAG_MASK);// 如果为空闲块if (is_free(next_block_size_val)) {// 下一个块的大小base_type next_block_size = (next_block_size_val >> BLOCK_FLAG_BITS);if (DEBUG_MODE)printf("merge current block(addr:%p size:%d) and next block(addr:%p size:%d) into", pt, size, next_block, next_block_size);remove_from_free_list(next_block);set_block_size(pt, size + next_block_size, BLOCK_USED);if (DEBUG_MODE)printf("new block(addr:%p, size:%d)\n", pt, block_size(pt));}}if (DEBUG_MODE)printf("----------------------------------free analysis end---------------------------------------------\n");return pt;
}int mm_init (void) {// print_type_info();base_type r = BASE_TYPE(mem_sbrk(HD_SIZE));if (r == -1)return -1;set_hd_inited();// 将各个链表的指针设置为NULLfor (base_type i = 1; i <= FB_LIST_NUM; i++)hd_write(i, NULL);// printf("low: 0x%x, high:0x%x\n", mem_heap_lo(), mem_heap_hi());// px(mem_heap_lo(), 5);return 0;
}void * mm_malloc (size_t size) {if (!size)  return NULL;if (hd_inited != INITED) {printf("error: try to call malloc before inited.\n");return NULL;}base_type total_size = calc_blcok_total_size(size);base_pt pt = search_free_list(total_size);if (pt == NULL) {//  请参考merge_prev_next_blockbase_type alloc_size = total_size;base_pt prev_block_size_pt = inc_n_byte(mem_heap_hi(), -(BASE_TYPE_SIZE - 1));if (DEBUG_MODE) {base_type size_val = *prev_block_size_pt;printf("prev_block_size_pt:%p heap_start:%p, size:%d, flag:%d\n", prev_block_size_pt, HEAP_START_PT, size_val >> BLOCK_FLAG_BITS, size_val & BLOCK_FLAG_MASK);}if (prev_block_size_pt > HEAP_START_PT & is_free((*prev_block_size_pt))) {// 在没有适合的空闲块时,要分配一个,如前面一个块为空闲块,则可以减少分配量base_type prev_block_size = ((*prev_block_size_pt) >> BLOCK_FLAG_BITS);base_pt new_block = true_malloc(total_size - prev_block_size + OV_SIZE);if (DEBUG_MODE) {printf("malloc: prev block(addr:%p size:%d flag:%d)\n", 0, prev_block_size, ((*prev_block_size_pt) & BLOCK_FLAG_MASK));printf("true malloc: block(addr:%p size:%d flag:%d)\n", new_block, block_size(new_block), block_flag(new_block));}base_pt merged_pt = merge_prev_next_block(new_block);if (DEBUG_MODE) {printf("malloc: request size: %d, allocated addr: %p, size: %d\n", size, merged_pt, block_size(merged_pt));print_list();}return merged_pt;}// 直接向系统申请分配void *r =  true_malloc(total_size);if (DEBUG_MODE) {printf("malloc: request size: %d, allocated addr: %p, size: %d\n", size, r, block_size(r));print_list();}return r;}else {// 存在所需的空闲块,对其进行分裂void *r = split_block(pt, total_size);if (DEBUG_MODE) {printf("malloc: request size: %d, allocated addr: %p, size: %d\n", size, r, block_size(r));print_list();}return r;}
}void mm_free(void *ptr) {if (hd_inited != INITED) {printf("free rror: try to call free before inited.\n");return;}if (is_block_free(ptr)) {printf("free error: try to free a free block with addr: %p\n", ptr);return;}if (DEBUG_MODE)printf("free: try to free a block with addr:%p, size:%d\n", ptr, block_size(ptr));// 先合并前后的空闲块,再插入空闲块链表base_pt pt = merge_prev_next_block(ptr);insert_into_free_list_head(pt);if (DEBUG_MODE)print_list();
}void *mm_realloc(void *ptr, size_t size) {if (hd_inited != INITED) {printf("error: try to call realloc before inited.\n");return NULL;}if (DEBUG_MODE)printf("realloc: try to realloc a block with addr:%p, size:%d\n", ptr, size);if (!ptr)   return mm_malloc(size);if (!size)  {mm_free(ptr);return NULL;}base_type blockSize = block_size(ptr);base_type needed_total_size = calc_blcok_total_size(size);if (needed_total_size <= blockSize) {if (DEBUG_MODE)print_list();return ptr;}// 当前后可能有空闲块时,可以合并后再看能否满足用户的需要else {// 下面这种实现不对,在mm_malloc中如果调用了split_block,那么会修改块尾部的长度值,可能篡改原来block数据// mm_free(ptr);// base_pt new_ptr = mm_malloc(size);// if (!new_ptr)   return NULL;// if (DEBUG_MODE)//     printf("realloc: origin block(addr:%p, size:%d), new block(addr:%p, size:%d)\n", ptr, block_size(ptr), new_ptr, block_size(new_ptr));// memcpy(new_ptr, ptr, blockSize - OV_SIZE);// if (DEBUG_MODE) {//     printf("copy from old block to new block finished, total copy size:%d!\n", blockSize - OV_SIZE);//     print_list();// }// return new_ptr;// 正确的实现// 先将前后的块合并base_pt merged_pt = merge_prev_next_block(ptr);base_type merged_block_size = block_size(merged_pt);base_pt final_block;// 合并块大小不够用就直接mallocif (merged_block_size < needed_total_size) {insert_into_free_list_head(merged_pt);final_block = mm_malloc(size);memcpy(final_block, ptr, blockSize - OV_SIZE);return final_block;}// 合并块够大就需要拆分else if (merged_block_size >= (needed_total_size + EXTRA_SAPCE)) {final_block = merged_pt;// 必须先将块的内容复制过去,再拷贝memcpy(final_block, ptr, blockSize - OV_SIZE);base_pt new_block = inc_n_byte(final_block, needed_total_size);set_block_used(final_block, needed_total_size);set_block_free(new_block, merged_block_size - needed_total_size);if (DEBUG_MODE)printf("split free block(addr:%p, size:%d) into ret block(addr:%p, size:%d) and ", merged_pt, merged_block_size, merged_pt, block_size(merged_pt));if (DEBUG_MODE)printf("new block(addr:%p, size:%d)\n", new_block, block_size(new_block));insert_into_free_list_head(new_block);return final_block;}// 块够用但不够拆分else {final_block = merged_pt;memcpy(final_block, ptr, blockSize - OV_SIZE);return final_block;}}
}

CSAPP Lab5: Malloc相关推荐

  1. CSAPP Lab5实验记录 ---- Shell Lab(实验分析 + 完整代码)

    文章目录 Lab 总结博客链接 前引 Lab5 Shell Lab 1.获取相关Lab材料 2.Overview(总览) 3.Explore(实现前的摸索) 4.函数实现 + 实现代码分析 1.eva ...

  2. 哈工大 csapp lab5

    实验报告 实 验(五) 题 目 LinkLab 链接 专 业 计算机科学与技术 学 号 190110812 班 级 7 学 生 刘新晨 指 导 教 师 吴锐 实 验 地 点 G707 实 验 日 期 ...

  3. 《深入理解计算机系统》(CSAPP)实验七 —— Malloc Lab

    文章目录 隐式空闲链表 分离的空闲链表 显示空闲链表 1. 实验目的 2. 背景知识 3. Implicit list mm_init extend_heap mm_malloc find_fit p ...

  4. CSAPP Lab6:Malloc

    文章目录 一.实验简介 二.隐式链表实现 基本宏 块的相关函数 mm_init mm_malloc mm_free mm_realloc extend_heap blk_merge blk_find ...

  5. HIT CSAPP 自设实验 Lab5 链接 Linkbomb 解析

    之前的方法太坑了,我更新了一下phase2 _(:з」∠)_  55555 直接复制过来排版太烂,我也懒得改了_(:з」∠)_,如果看的不舒服,移步: hahalidaxin's Github upd ...

  6. 【❌❌深入浅出,九浅一深⭕⭕】《深入理解计算机系统》CSAPP

    <计算机系统基础>30' 一.处理器的时序电路 1.CPU中的时序电路 答: CPU中的时序电路:通过RS触发器控制CPU的时序. 2.单周期处理器的设计 答: CPU在处理指令时,一般需 ...

  7. 《深入理解计算机系统》CSAPP

    <计算机系统基础>30' 一.处理器的时序电路 1.CPU中的时序电路 答: CPU中的时序电路:通过RS触发器控制CPU的时序. 2.单周期处理器的设计 答: CPU在处理指令时,一般需 ...

  8. CSAPP Lab2 实验记录 ---- Bomb Lab(Phase 1 - Phase 6详细解答 + Secret Phase彩蛋解析)

    文章目录 Lab 总结博客链接 实验前提引子 实验需要指令及准备 Phase 1 Phase 2 Phase 3 Phase 4 Phase 5 Phase 6 Phase Secret(彩蛋Phas ...

  9. CSAPP HITICS 大作业 hello's P2P by zsz

    摘 要 摘要是论文内容的高度概括,应具有独立性和自含性,即不阅读论文的全文,就能获得必要的信息.摘要应包括本论文的目的.主要内容.方法.成果及其理论与实际意义.摘要中不宜使用公式.结构式.图表和非公知 ...

最新文章

  1. 云计算究竟能帮你具体做些什么事?
  2. 试论敏捷开发方法的共同特征
  3. 巧妙解决:access denied (javax.management.MBeanTrust...
  4. How to Secure Your Smart Contracts: 6 Solidity Vulnerabilities and how to avoid them (Part 1)
  5. H264实时编码及NALU,RTP传输(ZZ)
  6. Samsung原版44B0X的Bootloader分析
  7. crv仪表上的i是什么指示灯_汽车打不着火是怎么回事,仪表盘汽车发动机故障灯亮是什么情况故障指示灯图解大全集...
  8. DPDK l3fwd
  9. Sublime 格式化 JSON
  10. ERP实施--常见问题
  11. hdu - 5033 - Building(单调栈)
  12. 为VSCode 设置好看的字体:Operator Mono
  13. shell 追加指定内容至某文件
  14. (C语言)用函数实现求三个数最大值
  15. Sqli-labs Less7
  16. 吞吐量和IOPS测试
  17. 字号,行距,磅,像素……(word排版)
  18. Robert Sedgewick左倾红黑树论文翻译
  19. 在计算机桌面怎样写提示语,桌面标语-标语桌面请保持-保持桌面干净标语
  20. 彻底卸载Windows 10自带的杀毒软件windows defender

热门文章

  1. [20161012]数据文件offline马上执行recover
  2. 华南农业大学java上机答案_华南农业大学Java程序设计(A卷)答案
  3. 5G计算机应用基础混合式教学,5G时代重新定义课堂教学
  4. 非结构化数据更需中台,企业内容管理未来走向何方
  5. 有哪些优秀的职场沟通基础思路?
  6. 显著性检测论文集合【1】
  7. java关于NEC的红外解码_红外协议之NEC协议
  8. cesium加载wsm服务
  9. 机器视觉到底前景如何?该不该从事视觉+自动化这个方向?
  10. what is a hacker