简体   繁体   中英

My malloc doesn't update the heap properly

I'm trying to implement my own malloc and then test it by dumping the heap to see what I've managed to accomplish. It compiles fine but when I run it, I get the output of

head->[1:0:8]->NULL
this is a test program

after which it promptly crashes. It looks like the way I implemented my malloc, it is able to allocate the space for *this and *is, but that's all. Anyone have any ideas why this might be?

My main.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>


#define MALLOC(n) my_malloc(n)
#define DUMP_HEAP() dump_heap()
void* my_malloc(int);

int main()
{
  char *this = MALLOC(5);
  char *is = MALLOC(3);
  char *a = MALLOC(2);
  char *test = MALLOC(5);
  DUMP_HEAP();

  strcpy(this, "this");
  strcpy(is, "is");
  strcpy(a, "a");
  strcpy(test, "test");
  strcpy(program, "program");
  printf("%s %s %s %s %s\n", this, is, a, test, program);
  DUMP_HEAP();

  return 0;
}

My malloc.c

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>

struct Block 
{
    int occ;             
    int size;            
    struct Block *prev;   
    struct Block *next;  
};

static struct Block *head = NULL; 

void *my_malloc(int size)
{
    void *pointer;
    pointer = (void*)sbrk(size);
    if(head == NULL)
    {
            head = pointer;
            head->occ = 1;
            head->prev=NULL;
            head->next=NULL;
            head->size = size;

            return (void*)head+sizeof(struct Block);
    }
    else
    {
            struct Block* new ;
            new = pointer;
            head->next = new;
            new->size = size;
            new->occ = 1;
            new->prev = head;
            new->next = NULL;
            head = new;

            return (void*)new+sizeof(struct Block);
    }
}

void dump_heap()
{
  struct Block *cur;
  printf("head->");
  for(cur = head; cur != NULL; cur = cur->next) 
  {
    printf("[%d:%d:%d]->", cur->occ, (char*)cur - (char*)head, cur->size);
    assert((char*)cur >= (char*)head && (char*)cur + cur->size < (char*)sbrk(0));
    if(cur->next != NULL) assert(cur->next->prev == cur); 
  }
  printf("NULL\n");
}

You aren't accounting for the size of the Block struct when asking the system for memory.

Compare this line:

pointer = (void*)sbrk(size);

to how you're attempting to account for the struct later:

return (void*)head+sizeof(struct Block);

You should be accounting for the size of the Block in the sbrk call:

pointer = (void*)sbrk(size + sizeof(struct Block));

Also, as has been pointed out, you should not do pointer arithmetic on void* . So your return statements should leave the head pointer uncasted and just add 1 to account for the block size:

return (void*)(head + 1);

Also also, upon further discussion it is clear that head is being used as the tail of the linked list. This introduces a bug in dump_heap . You may want to rename head to tail and maintain a proper head , one which only ever changes in malloc when it was previously NULL .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM