Skip to content

Instantly share code, notes, and snippets.

@JZHeadley
Last active October 23, 2016 03:20
Show Gist options
  • Select an option

  • Save JZHeadley/c5f614ba9c3182775372418fc428b91d to your computer and use it in GitHub Desktop.

Select an option

Save JZHeadley/c5f614ba9c3182775372418fc428b91d to your computer and use it in GitHub Desktop.

Revisions

  1. JZHeadley revised this gist Oct 23, 2016. 1 changed file with 135 additions and 0 deletions.
    135 changes: 135 additions & 0 deletions malloc-support.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,135 @@
    #include "malloc-support.h"

    #include <assert.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>

    #define META_SIZE sizeof(struct block_meta)
    void *global_base = NULL;

    void *nofree_malloc(size_t size) {
    void *p = sbrk(0);
    void *request = sbrk(size);
    if (request == (void *) -1) {
    return NULL; // sbrk failed
    } else {
    assert(p == request); // Not thread safe.
    return p;
    }
    }

    struct block_meta {
    size_t size;
    struct block_meta *next;
    int free;
    int magic; // For debugging only. TODO: remove this in non-debug mode.
    };

    // Iterate through blocks until we find one that's large enough.
    // TODO: split block up if it's larger than necessary
    struct block_meta *find_free_block(struct block_meta **last, size_t size) {
    struct block_meta *current = global_base;
    while (current && !(current->free && current->size >= size)) {
    *last = current;
    current = current->next;
    }
    return current;
    }

    struct block_meta *request_space(struct block_meta *last, size_t size) {
    struct block_meta *block;
    block = sbrk(0);
    void *request = sbrk(size + META_SIZE);
    assert((void * ) block == request); // Not thread safe.
    if (request == (void *) -1) {
    return NULL; // sbrk failed.
    }

    if (last) // NULL on first request.
    {
    last->next = block;
    }
    block->size = size;
    block->next = NULL;
    block->free = 0;
    block->magic = 0x12345678;
    return block;
    }

    void *malloc(size_t size) {
    struct block_meta *block;
    if (size <= 0) {
    return NULL;
    }
    if (!global_base) {
    block = request_space(NULL, size);
    if (!block) {
    return NULL;
    }
    global_base = block;
    } else {
    struct block_meta *last = global_base;
    block = find_free_block(&last, size);
    if (!block) // Failed to find free block.
    {
    block = request_space(last, size);
    if (!block) {
    return NULL;
    }
    } else // Found free block
    {
    // TODO: consider splitting block here.
    block->free = 0;
    block->magic = 0x77777777;
    }
    }

    return (block + 1);
    }

    void *calloc(size_t nelem, size_t elsize) {
    size_t size = nelem * elsize; // TODO: Check for overflow
    void *ptr = malloc(size);
    memset(ptr, 0, size);
    return ptr;
    }

    struct block_meta *get_block_ptr(void *ptr) {
    return (struct block_meta *) ptr - 1;
    }
    ;

    void free(void *ptr) {
    if (!ptr) {
    return;
    }

    // TODO: consider merging blocks once splitting blocks is implemented.
    struct block_meta *block_ptr = get_block_ptr(ptr);
    assert(block_ptr->free == 0);
    assert(block_ptr->magic == 0x77777777 || block_ptr->magic == 0x12345678);
    block_ptr->free = 1;
    block_ptr->magic = 0x55555555;
    }

    void *realloc(void *ptr, size_t size) {
    if (!ptr) {
    // NULL ptr. realloc should act like malloc.
    return malloc(size);
    }

    struct block_meta *block_ptr = get_block_ptr(ptr);
    if (block_ptr->size >= size) {
    return ptr;
    }
    void *new_ptr;
    new_ptr = malloc(size);
    if (!new_ptr) {
    return NULL;
    }
    memcpy(new_ptr, ptr, block_ptr->size);
    free(ptr);
    return new_ptr;
    }

  2. JZHeadley created this gist Oct 23, 2016.
    24 changes: 24 additions & 0 deletions Makefile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    INCLUDES=-I.
    CC=gcc
    CFLAGS=-I. -c -g -Wall $(INCLUDES)
    FLAGS = -O0 -W -Wall -Wextra -g
    LINKARGS=-lm
    LIBS=-lm

    # Productions
    all : assign2

    assign2 : assign2.o malloc.so
    $(CC) $(LINKARGS) $^ -o $@ $(LIBS)

    malloc.so: malloc-support.c malloc-support.h
    $(CC) $^ $(FLAGS) -o $@ -shared -fPIC

    assign2.o : assign2.c malloc-support.h
    $(CC) $< $(CFLAGS) -o $@

    clean :
    rm -f malloc.so assign2.o assign2

    run :
    valgrind ./assign2
    17 changes: 17 additions & 0 deletions assign2.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    #include <stdio.h>
    #include "malloc-support.h"

    int main() {
    int *ptr = malloc(sizeof(int));
    if (ptr == NULL) {
    printf("couldn't malloc an int");
    return 1;
    }
    *ptr = 1;
    *ptr = 100;

    free(ptr);

    printf("freed the int after assigning it a value");
    return 0;
    }
    27 changes: 27 additions & 0 deletions malloc-support.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    #include <assert.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>

    #ifndef MALLOC_SUPPORT_H_
    #define MALLOC_SUPPORT_H_

    struct block_meta;

    struct block_meta *find_free_block(struct block_meta **last, size_t size);

    struct block_meta *request_space(struct block_meta *last, size_t size);

    struct block_meta *get_block_ptr(void *ptr);

    void *nofree_malloc(size_t size);

    void *malloc(size_t size);

    void *calloc(size_t nelem, size_t elsize);

    void free(void *ptr);

    void *realloc(void *ptr, size_t size);

    #endif