This homework is due on Thursday, March 31, at 11:59:59 PM (Eastern daylight time). You must use submit to turn in your homework like so: submit cs421_jtang hw4 hw4.c
Your program must be named hw4.c, and it will be compiled on Ubuntu 14.04 as follows:
gcc --std=c99 -Wall -O2 -o hw4 hw4.c hw4_test.cThere must not be any compilation warnings in your submission; warnings will result in grading penalties. In addition, your code must be properly indented and have a file header comment, as described on the coding conventions page.
In this homework, you are writing a memory allocator from scratch. You will implement a first-fit allocation algorithm. As proof that your code works, your program will run instructor-provided unit tests that will exercise all functions.
Your program will simulate a machine's memory system. The machine has 16 page frames, where each frame holds 32 bytes, for 512 bytes total. Declare this "memory" as a global array. When your program starts, initialize its contents to 0.
Implement the following function with this given signature:
/** * Display information about memory allocations to standard output. * * Display to standard output the following: * - Memory contents, one frame per line, 16 lines total. Display the * actual bytes stored in memory. If the byte is unprintable (ASCII * value less than 32 or greater than 126), then display a dot * instead. * - Current memory allocations, one line of 32 characters, where each * character corresponds to a frame. Indicate reserved frames with * R, free memory with f. */ void my_malloc_stats(void);
Next, implement a first-fit memory allocator. You must implement these functions with these given signatures:
/** * Allocate and return a contiguous memory block that is within the * memory region. * * The size of the returned block will be at least @a size bytes, * rounded up to the next 32-byte increment. * * @param size Number of bytes to allocate. If @c 0, your code may do * whatever it wants; my_malloc() of @c 0 is "implementation defined", * meaning it is up to you if you want to return @c NULL, segfault, * whatever. * * @return Pointer to allocated memory, or @c NULL if no space could * be found. If out of memory, set errno to @c ENOMEM. */ void *my_malloc(size_t size); /** * Deallocate a memory region that was returned by my_malloc() or * my_realloc(). * * If @a ptr is not a pointer returned by my_malloc() or my_realloc(), * then send a SIGSEGV signal to the calling process. Likewise, * calling my_free() on a previously freed region results in a * SIGSEGV. * * @param ptr Pointer to memory region to free. If @c NULL, do * nothing. */ void my_free(void *ptr);
For my_malloc()
, you are to implement a first-fit
allocation strategy. Because each page frame is 32
bytes, my_malloc()
must round up to the next 32-byte
boundary when reserving space, and the returned address must be
frame-aligned. Your function allocates using the space reserved in
step 1 above.
For my_free()
, your program deallocates space that was
returned by my_malloc()
or my_realloc()
(see below). Thus, if my_malloc()
previously allocated
5 frames and returned the address to the first frame,
calling my_free()
will deallocate all 5 frames (not
just the first).
In your code, add a comment block describing how you track which frames are allocated and how large each memory block is. Specifically, describe how your code would handle these two scenarios:
my_free()
would know to
deallocate 5 frames if the user had previously
called my_malloc()
for 150 bytes?
my_free()
know it needs to send a SEGFAULT
if the user tries to free a pointer that points into the middle
of a memory block?
Next, implement this function with this given signature:
/** * Change the size of the memory block pointed to by @a ptr. * * - If @a ptr is @c NULL, then treat this as if a call to * my_malloc() for the requested size. * - Else if @a size is @c 0, then treat this as if a call to * my_free(). * - Else if @a ptr is not a pointer returned by my_malloc() or * my_realloc(), then send a SIGSEGV signal to the calling process. * * Otherwise reallocate @a ptr as follows: * * - If @a size is smaller than the previously allocated size, then * reduce the size of the memory block. Mark the excess memory as * available. Memory sizes are rounded up to the next 32-byte * increment. * - If @a size is the same size as the previously allocated size, * then do nothing. * - If @a size is greater than the previously allocated size, then * allocate a new contiguous block of at least @a size bytes, * rounded up to the next 32-byte increment. Copy the contents from * the old to the new block, then free the old block. * * @param ptr Pointer to memory region to reallocate. * @param size Number of bytes to reallocate. * * @return If allocating a new memory block or if resizing a block, * then pointer to allocated memory; @a ptr will become invalid. If * freeing a memory region or if allocation fails, return @c NULL. If * out of memory, set errno to @c ENOMEM. */ void *my_realloc(void *ptr, size_t size);
Your my_realloc()
(if size
is
not 0) must use the same first-fit allocation strategy
as my_malloc()
. Likewise, the returned pointer must be
frame-aligned.
Within your Ubuntu VM, use the wget command to fetch the unit test code file http://www.csee.umbc.edu/~jtang/cs421.s16/homework/hw4_test.c. This file declares a function with the following signature:
/** * Unit test of your memory allocator implementation. This will * allocate and free memory regions. */ extern void hw4_test(void);In your
main()
function, after you have initialized
your memory, call hw4_test()
.
The grader will use a different unit test code file during
grading. You may not make any assumptions about
what hw4_test()
will do other than that its code
will compile and that it will not have compilation warnings.
Note how this code implements a basic testing framework, that prints what it is about to test, if the test passes or fails, and the sum of passed and faild tests. Read over hw4_test.c; for the projects you will need to write your own unit tests. If you continue your career in software engineering, be familiar with other unit testing frameworks.
Here is a sample output from running the program using the above hw4_test.c.
Test 1: Display initialized memory Memory contents: ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ Memory allocations: ffffffffffffffff Test 2: Simple allocations Test 3: Simple freeing Memory contents: CCCCCCCCAAAAAAAAAAAAAAAAAAAAAA.. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB B............................... ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ Memory allocations: fRRfffffffffffff Test 4: Out of memory condition Test 5: Double-free Caught signal 11: Segmentation fault: 11! Memory contents: CCCCCCCCAAAAAAAAAAAAAAAAAAAAAA.. BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB B............................... ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ ................................ Memory allocations: ffffffffffffffff Test 6: Increasing memory Memory contents: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD D............................... DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD D............................... ................................ ................................ ................................ ................................ ................................ ................................ Memory allocations: fffffRRRRRRfffff Test 7: Decreasing memory Memory contents: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD D............................... DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE ................................ Memory allocations: fffffRRRRRRRRRRf 11 tests passed, 0 tests failed.
malloc()
/calloc()
/realloc()
(or any of its ilk) or
free()
. Using any built-in memory allocator
will result in a zero for this assignment.
int
, size_t
,
and ptrdiff_t
.
ALIGN
macro.
You may earn an additional 5% on this assignment by implementing the following function:
/** * Format a string into a newly allocated memory block. * * Calculate the length that a formatted string (as per snprintf()) * would be, then allocate contiguous memory block(s) of at least that * length. Then output the resulting string, including terminating * null character ('\0') to that memory. The starting address of the * memory block is written to the pointer pointed to by @a strp. The * pointer can be freed via my_free() afterwards. * * @param strp Pointer to where to write pointer to. * * @param fmt Format specification, as per snprintf(). * * @return Number of bytes allocated (excluding terminating null * byte), if memory allocation succeeds. If out of memory, @a strp is * @c NULL, or some other error occurs, return -1. */ int my_asprintf(char **strp, const char *fmt, ...);
If you choose to perform this extra credit, put a comment at the top of your file, alerting the grader.