CSAPP Experiment 5: Dynamic Memory Allocation (Malloc lab)

       This series of articles is an experiment arranged by the basic course "Computer System" of the computer major of the University of Science and Technology of China. The teaching materials and content used in the class are the black book CSAPP. At that time, it took a lot of energy and detours. Now I will summarize each experiment. This article is the fifth An experiment - dynamic memory allocation (Malloc lab).

1. Experiment name: Malloc lab 

2. Experimental hours: 3

3. Experiment content and purpose:

     1. Purpose

       /afs/cs/project/ics/im/labs/malloclab/

       In this experiment, a dynamic storage allocator needs to be implemented in C language. Need to implement malloc, free, realloc and other functions. Of course, it is not only necessary to correctly implement the relevant functions, but also to meet the requirements of speed and efficiency.

     2. Steps

tar xvf malloclab-handout.tar解压文件

我们需要修改的唯一文件是mm.c,包含如下几个需要实现的函数

int mm_init(void);

void *mm_malloc(size_t size);

void mm_free(void *ptr);

void *mm_realloc(void *ptr, size_t size)

    3.  Explain

mm_init:在调用mm_malloc,mm_realloc或mm_free之前,调用mm_init进行初始化,正确返回0。

mm_malloc:在堆区域分配指定大小的块,分配的空间,返回的指针应该是8字节对齐的

mm_free:释放指针指向的block

mm_realloc:返回指向一个大小为size的区域指针,满足一下条件:

if ptr is NULL, the call is equivalent to mm_malloc(size);

if size is equal to zero, the call is equivalent to mm_free(ptr);

if ptr is not NULL:先按照size指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来ptr所指内存区域

    4. Functions that can be called

void *mem_sbrk(int incr): Expands the heap by incr bytes, where incr is apositive non-zero integer and returns a generic pointer to the first byte of the newly allocated heap area. 
void *mem_heap_lo(void):Returns a generic pointer to the first byte in the heap. 
void *mem_heap_hi(void): Returns a generic pointer to the last byte in the heap. 
size_t mem_heapsize(void):Returns the current size of the heap in bytes. 
size_t mem_pagesize(void): Returns the system’s page size in bytes (4K onLinux systems). 

    5. Verification method

mdriver.c:负责测试mm.c的正确性,空间利用率和吞吐量
-f <tracefile>:  -f后添加一些trace file来测试我们实现的函数
-V:打印出诊断信息
./mdriver -V  -f short1-bal.rep

    6. Programming Rules

    Cannot change the function interface in mm.c

    Cannot directly call any memory management library functions and system functions malloc, calloc, free, realloc, sbrk, brk

    Cannot define any global or static composite data structures such as arrays, structs, trees, allows simple data types such as integers, floats, and pointers

    Just submit mm.c file

   4. Experimental steps and results: 

   1. mm_init function

     The organization method of the free block - the Segregated free list method 
     The classification method of the size classes in the segregated free list is as follows, and the list table is placed at the head of the heap, and it is isolated from the data through the preamble block. Within each size class, free blocks are sorted by size from largest to smallest.

*
* mm_init - initialize the malloc package.
* The return value should be -1 if there was a problem in performing the initialization, 0 otherwise
*/
int mm_init(void)
{
int listnumber;
char *heap; 

/* 初始化分离空闲链表 */
for (listnumber = 0; listnumber < LISTMAX; listnumber++)
{
segregated_free_lists[listnumber] = NULL;
}
/* 初始化堆 */
if ((long)(heap = mem_sbrk(4 * WSIZE)) == -1)
return -1;
/* 这里的结构参见本文上面的“堆的起始和结束结构” */
PUT(heap, 0);
PUT(heap + (1 * WSIZE), PACK(DSIZE, 1));
PUT(heap + (2 * WSIZE), PACK(DSIZE, 1));
PUT(heap + (3 * WSIZE), PACK(0, 1));
/* 扩展堆 */
if (extend_heap(INITCHUNKSIZE) == NULL)
return -1;
return 0;
}

      Free block finding method - best fit

      Because the free blocks in the same size class are sorted from small to large, the first suitable one is the most suitable mm_malloc function.

    2.mm_malloc function

/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
*/
void *mm_malloc(size_t size)
{
if (size == 0)
return NULL;
/* 内存对齐 */
if (size <= DSIZE)
{
size = 2 * DSIZE;
}
else
{
size = ALIGN(size + DSIZE);
}

int listnumber = 0;
size_t searchsize = size;
void *ptr = NULL;
while (listnumber < LISTMAX)
{
/* 寻找对应链 */
if (((searchsize <= 1) && (segregated_free_lists[listnumber] != NULL)))
{
ptr = segregated_free_lists[listnumber];
/* 在该链寻找大小合适的free块 */
while ((ptr != NULL) && ((size > GET_SIZE(HDRP(ptr)))))
{
ptr = PRED(ptr);
}
/* 找到对应的free块 */
if (ptr != NULL)
break;
}
searchsize >>= 1;
listnumber++;
}
/* 没有找到合适的free块,扩展堆 */
if (ptr == NULL)
{
if ((ptr = extend_heap(MAX(size, CHUNKSIZE))) == NULL)
return NULL;
}
/* 在free块中allocate size大小的块 */
ptr = place(ptr, size);
return ptr;
}

     3. mm_free function

/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *ptr)
{
size_t size = GET_SIZE(HDRP(ptr));

PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
/* 插入分离空闲链表 */
insert_node(ptr, size);
/* 注意合并 */
coalesce(ptr);
}

    4.  mm_realloc function

       mm_realloc improvements:

       For the case where the requested newsize>original oldsize, we will use a method similar to coalesce to check whether there are free blocks before and after, and whether the size of the free blocks before and after and the currently allocated free blocks is greater than newsize, if If it is, it is merged, and there is no need to re-request free blocks. If not, you need to mm_malloc a new space.

/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
void *new_block = ptr;
int remainder;
if (size == 0)
return NULL;
/* 内存对齐 */
if (size <= DSIZE)
{
size = 2 * DSIZE;
}
else
{
size = ALIGN(size + DSIZE);
}
/* 如果size小于原来块的大小,直接返回原来的块 */
if ((remainder = GET_SIZE(HDRP(ptr)) - size) >= 0)
{
return ptr;
}
/* 否则先检查地址连续下一个块是否为free块或者该块是堆的结束块,因为我们要尽可能利用相邻的free块,以此减小“external fragmentation” */
else if (!GET_ALLOC(HDRP(NEXT_BLKP(ptr))) || !GET_SIZE(HDRP(NEXT_BLKP(ptr))))
{
/* 即使加上后面连续地址上的free块空间也不够,需要扩展块 */
if ((remainder = GET_SIZE(HDRP(ptr)) + GET_SIZE(HDRP(NEXT_BLKP(ptr))) - size) < 0)
{
if (extend_heap(MAX(-remainder, CHUNKSIZE)) == NULL)
return NULL;
remainder += MAX(-remainder, CHUNKSIZE);
}
/* 删除刚刚利用的free块并设置新块的头尾 */
delete_node(NEXT_BLKP(ptr));
PUT(HDRP(ptr), PACK(size + remainder, 1));
PUT(FTRP(ptr), PACK(size + remainder, 1));
}
/* 没有可以利用的连续free块,而且size大于原来的块,这时只能申请新的不连续的free块、复制原块内容、释放原块 */
else
{
new_block = mm_malloc(size);
memcpy(new_block, ptr, GET_SIZE(HDRP(ptr)));
mm_free(ptr);
}
return new_block;
}

    5. Experimental results 

 Test Case 1: 99 points

Test Case 2: 93 points

Guess you like

Origin blog.csdn.net/qq_35739903/article/details/119654444