//free the middle chunk, than the first chunk, leading to a merge with the head of the list void merge_with_head() { free_without_merging(); //free middle chunk first void *p = get_heap_base(); // the first allocated chunk on the heap Free_Header *freelist0 = get_freelist(); //get the head of freelist, which is the middle chunk assert_addr_not_equal(freelist0, p); Free_Header *next = freelist0->next; free(p); //free the chunk before head of the free list, need to merge Free_Header *freelist1 = get_freelist(); //get the new freelist assert_addr_equal(freelist1, p); // new head is at the base of heap assert_addr_not_equal(freelist1, freelist0); assert_addr_not_equal(freelist1->next, freelist0); assert_addr_equal(freelist1->next, next); assert_addr_equal(freelist1->prev, NULL); assert_addr_equal(next->next, NULL); assert_addr_equal(next->prev, freelist1); Heap_Info info = verify_heap(); assert_equal(info.busy, 1); assert_equal(info.free, 2); assert_equal(info.free_size, HEAP_SIZE - info.busy_size); assert_equal(freelist1->next->size, info.free_size-freelist1->size); assert_equal(find_next(find_next(freelist1)), freelist1->next); }
void bin_malloc_free_malloc() { // test bin malloc and free void *p = malloc(99); // should split heap into two chunks assert_addr_not_equal(p, NULL); Free_Header *freelist = get_heap_freelist(); Busy_Header *heap = get_heap_base(); assert_addr_not_equal(freelist, heap); // check 1st chunk assert_equal(p, heap); assert_equal(chunksize(p), request2size(99)); // check 2nd chunk assert_equal(freelist->size, HEAP_SIZE-request2size(99)); assert_addr_equal(freelist->next, NULL); Free_Header *freelist1 = get_bin_freelist(99);// freelist of bin should be NULL free(p); // free to bin Free_Header *freelist2 = get_bin_freelist(99);// freelist of bin should be have one element p assert_addr_not_equal(freelist1,freelist2); void *p1 = malloc(99); // this malloc should be from bin assert_addr_not_equal(p1, NULL); Free_Header *freelist3 = get_bin_freelist(99); // freelist of bin should be NULL assert_addr_equal(freelist3,NULL); free(p1); Free_Header *freelist4 = get_bin_freelist(99); // freelist should have one element p1 assert_addr_equal(freelist2,freelist4); }
void malloc_large_size_then_free() { Free_Header *freelist = get_heap_freelist();//free list before malloc void *p = malloc(2048); assert_addr_not_equal(p, NULL); assert_equal(chunksize(p), request2size(2048)); Free_Header *freelist1 = get_heap_freelist(); // free list after malloc Busy_Header *heap = get_heap_base(); assert_addr_equal(p,heap); assert_addr_not_equal(heap,freelist1); free(p); Busy_Header *heap1 = get_heap_base(); Free_Header *freelist2 = get_heap_freelist(); // free list after free,should back to status before malloc assert_addr_equal(freelist,freelist2); assert_addr_equal(heap1,freelist2); }
void one_malloc() { void *p = malloc(100); assert_addr_not_equal(p, NULL); Free_Header *freelist = get_heap_freelist(); Busy_Header *heap = get_heap_base(); assert_addr_not_equal(freelist, heap); // check 1st chunk assert_equal(p, heap); assert_equal(chunksize(p), request2size(100)); // check 2nd chunk assert_equal(freelist->size, HEAP_SIZE-request2size(100)); assert_addr_equal(freelist->next, NULL); Heap_Info info = verify_heap(); assert_equal(info.busy, 1); assert_equal(info.busy_size, request2size(100)); assert_equal(info.free, 1); assert_equal(info.free_size, HEAP_SIZE - request2size(100)); }
void two_malloc() { one_malloc(); void *p0 = get_heap_base(); Free_Header *freelist0 = get_heap_freelist(); Busy_Header *p = malloc(200); assert_addr_not_equal(p, NULL); // check 2nd alloc chunk assert_equal(p, freelist0); // should return previous free chunk assert_equal(chunksize(p), request2size(200)); // check remaining free chunk Free_Header *freelist1 = get_heap_freelist(); assert_addr_not_equal(freelist0, freelist1); assert_addr_not_equal(freelist0, get_heap_base()); assert_equal(chunksize(freelist1), HEAP_SIZE-request2size(100)-request2size(200)); assert_equal(chunksize(p0)+chunksize(p)+chunksize(freelist1), HEAP_SIZE); assert_addr_equal(freelist1->next, NULL); Heap_Info info = verify_heap(); assert_equal(info.busy, 2); assert_equal(info.busy_size, request2size(100) + request2size(200)); assert_equal(info.free, 1); assert_equal(info.free_size, HEAP_SIZE - request2size(100) - request2size(200)); }
//free the chunk in the middle of three busy chunks void free_without_merging() { three_malloc(); Busy_Header *b_1 = get_heap_base(); Busy_Header *b_2 = find_next(b_1); Busy_Header *b_3 = find_next(b_2); Free_Header *freelist0 = get_freelist(); //get the head of freelist, which is at the end of allocated chunks assert_addr_equal(freelist0, find_next(b_3)); free(b_2); //free the chunk in the middle, which becomes the head of the new freelist Free_Header *freelist1 = get_freelist(); //get the new freelist assert_addr_not_equal(freelist1, b_1); assert_addr_not_equal(freelist0, freelist1); assert_addr_equal(freelist1, b_2); assert_addr_equal(freelist1->next, freelist0); //two free chunks in the list assert_equal(chunksize(b_1) + chunksize(b_2) + chunksize(b_3) + chunksize(freelist0), HEAP_SIZE); assert_equal(chunksize(b_1) + chunksize(b_3) + chunksize(freelist1) + chunksize(freelist0), HEAP_SIZE); Heap_Info info = verify_heap(); assert_equal(info.busy, 2); assert_equal(info.busy_size, chunksize(b_1) + chunksize(b_3)); assert_equal(info.free, 2); // 2 free chunks not next to each other assert_equal(info.free_size, chunksize(freelist1) + chunksize(freelist1->next)); }
void malloc_then_free() { one_malloc(); void *p = get_heap_base(); // should be allocated chunk Free_Header *freelist0 = get_freelist(); free(p); Free_Header *freelist1 = get_freelist(); // allocated chunk is freed and becomes head of new freelist assert_addr_equal(freelist1, p); assert_addr_equal(freelist1, get_heap_base()); assert_addr_not_equal(freelist0, freelist1); assert_equal(chunksize(freelist1) + chunksize(freelist1->next), HEAP_SIZE); Heap_Info info = verify_heap(); assert_equal(info.busy, 0); assert_equal(info.busy_size, 0); assert_equal(info.free, 1); // 1 free chunk after merging assert_equal(info.free_size, HEAP_SIZE); }
void bin_split_malloc_test(){ const int N = 1000; void *p = malloc(N); // get chunk from free list assert_addr_not_equal(p, NULL); Free_Header *freelist = get_bin_freelist(N); assert_addr_equal(freelist, NULL); // chunk not in bin N yet free(p); // free chunk and add to bin N Free_Header *freelist1 = get_bin_freelist(N); assert_addr_not_equal(freelist1, NULL); // now we have a chunk assert_addr_equal(p, freelist1); const int N2 = 512; void *p1 = malloc(2500); // get chunk from free list (beyond max bin size) assert_addr_not_equal(p1,NULL); Free_Header *freelist4 = get_bin_freelist(N-N2-sizeof(Busy_Header)); void *p2 = malloc(N2); // should get chunk from bin[request2size(N)],will split bin[request2size(N)] assert_addr_not_equal(p2,NULL); Free_Header *freelist2 = get_bin_freelist(N); assert_addr_not_equal(freelist1,freelist2); assert_addr_equal(freelist2,NULL); Free_Header *freelist3 = get_bin_freelist(N-N2-sizeof(Busy_Header)); assert_addr_not_equal(freelist3,NULL); assert_addr_not_equal(freelist3,freelist4); }
void malloc_word_size() { void *p = malloc(sizeof(void *)); assert_addr_not_equal(p, NULL); assert_equal(chunksize(p), MIN_CHUNK_SIZE); }
void malloc0() { void *p = malloc(0); assert_addr_not_equal(p, NULL); assert_equal(chunksize(p), MIN_CHUNK_SIZE); }
void freelist_free_stale() { malloc_large_size_then_free(); Free_Header *freelist = get_heap_freelist(); free(freelist); // NOT ok; freeing something already free'd assert_addr_not_equal(freelist, freelist->next); // make sure we didn't create cycle by freeing twice }
void malloc_2x_word_size() { void *p = malloc(2 * sizeof(void *)); assert_addr_not_equal(p, NULL); assert_equal(chunksize(p), 3 * sizeof(void *)); // 2 words + rounded up size field }
void test_core() { void *heap = morecore(HEAP_SIZE); assert_addr_not_equal(heap, NULL); dropcore(heap, HEAP_SIZE); }