malloc implementation Please give me some feedback to my malloc implementation.  I implemented this design to understand the basic concept.

#include &lt;stdio.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;string.h&gt;

#define HEAP_MEM_SIZE 150
#define MEMORY_AVAILABLE 1 
#define MEMORY_USED 0 

struct chunk_header {
  struct chunk_header *next; // next pointer on free list
  size_t size;               // the size of this chunk
  bool is_available;         // indicates if this chunk is MEMORY_AVAILABLE or MEMORY_USED
};

typedef struct chunk_header chunk_header;
chunk_header *chunk_header_begin;
static char buffer[HEAP_MEM_SIZE];
unsigned int heap_size;

void init() {
    heap_size = HEAP_MEM_SIZE;
    chunk_header_begin = (chunk_header*)&amp;buffer;
    chunk_header_begin-&gt;next = NULL;
    chunk_header_begin-&gt;size = heap_size;
    chunk_header_begin-&gt;is_available = MEMORY_AVAILABLE;
}

void init_next_chunk(chunk_header *curr, unsigned int bytes) {
    heap_size -= bytes;
    curr-&gt;next = NULL;
    curr-&gt;size = heap_size;
    curr-&gt;is_available = MEMORY_AVAILABLE;
}

void *my_malloc(unsigned int nbytes) {
    static bool init_flag = false;

    if(!init_flag) {
        init();
        init_flag = true;
    }

    int alloc_size = nbytes + sizeof(chunk_header); 
    chunk_header *curr = chunk_header_begin;

    while(curr) {
        if(curr-&gt;is_available &amp;&amp; curr-&gt;size &gt;= alloc_size) {
            curr-&gt;is_available = MEMORY_USED;
            curr-&gt;size = alloc_size;
            curr-&gt;next = curr + alloc_size;

            init_next_chunk(curr-&gt;next, alloc_size);

            // return memory region
            curr = curr + sizeof(chunk_header);
            return curr;
        }

        curr = curr-&gt;next;
    }

    return NULL;
}

void my_free(void *firstbyte) {
    chunk_header *mem = (chunk_header*)firstbyte - sizeof(chunk_header);
    chunk_header *curr = chunk_header_begin;

    while (curr) {
        if (curr == mem) {
            heap_size += curr-&gt;size;

            // Mark the block as being available
            curr-&gt;is_available = MEMORY_AVAILABLE;
            break;
        }

        curr = curr-&gt;next;
    }

    firstbyte = NULL;
}

void print_heap_allocations() {
    chunk_header *curr = chunk_header_begin;

    printf("\n\tSize\tAvailable\tMemory-Ptr");

    while (curr) {
        void *mem_ptr = curr + sizeof(chunk_header);
        printf("\n\t%d\t%d\t\t%x", curr-&gt;size, curr-&gt;is_available, mem_ptr);
        curr = curr-&gt;next;
    }

    printf("\n");
}

int main() {
    char *mem1 = (char*)my_malloc(20); 
    if(mem1 == NULL) {
        goto err;
    }
        memset (mem1,'x',19); 
        mem1[19] = '\0'; 

        print_heap_allocations();

        char *mem2 = (char*)my_malloc(20); 
        if(mem2 == NULL) {
        goto err;
    }
        memset (mem2,'y',19); 
        mem2[19] = '\0'; 

        print_heap_allocations();

        char *mem3 = (char*)my_malloc(20); 
        if(mem3 == NULL) {
            goto err;
        }
        memset (mem3,'z',19); 
        mem3[19] = '\0'; 

        print_heap_allocations();

    my_free(mem2);

    print_heap_allocations();

    char *mem4 = (char*)my_malloc(20);
    if(mem4 == NULL) {
        goto err;
    } 
        memset (mem4,'a',20); 
    mem4[19] = '\0';

        print_heap_allocations();

        printf("should be 19 x sein: %s\n", mem1); 
        printf("should be 19 a sein: %s\n", mem4); 
        printf("should be 19 z sein: %s\n", mem3);

    return 0;

err:
        printf("could not allocate mem\n");
        return 0;
}
Things you did well:


Some use of comments.
Use of typedef.


Things you could improve:

Syntax/Styling:


Never use goto.  



Yes, there are some rare situations where you may find it necessary to use it.  This is not one of them.


err:
        printf("could not allocate mem\n");
        return 0;



As you can see, all you do in your little block of code here is print out an unspecific error message,  and then exit (using 0, which means the program was successful and is contradictory here).

You should instead abolish the goto's completely.  Print out specific, useful error messages instead, and then return with a unique exit code.

if(mem2 == NULL) 
{
    fprintf(stderr, "Error allocating memory to mem2.\n");
    return -2;
}

Your format specifies type int when you are trying to print a string, but the argument has type size_t (basically, unsigned long).  Your format also specifies type unsigned int but the argument has type void *.


printf("\n\t%d\t%d\t\t%x", curr-&gt;size, curr-&gt;is_available, mem_ptr);



Just change they type you are trying to print out, and cast mem_ptr to an unsigned int.

printf("\n\t%zuu\t%d\t\t%x", curr-&gt;size, curr-&gt;is_available, (unsigned int) mem_ptr);

You aren't using standard naming conventions with your typedef struct.


typedef struct chunk_header chunk_header;




You should be giving the typedef a specific name, different from the abstract struct name.
You should be capitalizing the name of the type, or adding a _t to the end (though this is reserved in POSIX)

typedef your structs when you declare them.


struct chunk_header {
 struct chunk_header *next; // next pointer on free list
 size_t size;               // the size of this chunk
 bool is_available;         // indicates if this chunk is MEMORY_AVAILABLE or MEMORY_USED
};
typedef struct chunk_header chunk_header;



The typedef means you no longer have to write struct all over the place, as you have used it.  But you can combine these two parts to make things more simple:

typedef struct chunk_header
{
    struct chunk_header *next; // next pointer on free list
    size_t size;               // the size of this chunk
    bool is_available;         // indicates if this chunk is MEMORY_AVAILABLE or MEMORY_USED
} ChunkHeader;

You can simplify your NULL checks.


 if(mem1 == NULL)



Since NULL is defined as (void *)0, we can treat is as a comparison to 0.

if(!mem1)



Parameters/Returns:


You don't accept any parameters for some of your functions, such as main().  If you do not take in any parameters, declare them as void.

int main(void)

You should still return from a function, even if it is declared to return void.

void my_free(void *firstbyte) {
    ...
    return;
}



Compilation:


I can see from some warnings I received that you have not enabled all of your compiler warnings, which you should do.