При создании версии malloc в c возвращается неверный указатель - PullRequest
0 голосов
/ 13 ноября 2018

В чем причина этой ошибки? Я создаю персональную версию malloc и бесплатную для своего класса C, но столкнулся со следующей проблемой: я разделил свободное место на 2 узла, используя метод наилучшего соответствия, чтобы вставить значение в свой связанный список, однако он возвращает неверное значение программа тестирования. Значение currentBlock + sizeof (struct Block) равно 6299672, но когда я распечатываю его из программы тестирования, он печатает 6300251. Это приводит к ошибке сегмента из-за неверного указателя, когда я освобождаю его позже в программе. Это проблема неправильного приведения или я что-то упустил?

Спасибо! Соответствующие разделы моего кода ниже:

Ниже приведены методы my_malloc и my_free:

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

struct Block {
  int occ;              // whether block is occupied
  int size;             // size of block (including header)
  struct Block *prev;   // pointer to previous block
  struct Block *next;   // pointer to next block
};

static struct Block *head = NULL;       // head of list

void *my_malloc(int size)
{

  struct Block *currentBlock = head;
  struct Block *bestFitBlock = NULL;
  int bestFit = 0;

  void *offset = sbrk(0);
  void *ending = offset + size + sizeof(struct Block);
  int success = brk(ending);

  struct Block *newBlock = offset;
  newBlock -> occ = 1;
  newBlock -> size = size + sizeof(struct Block);

  while(head != NULL && currentBlock != NULL){
    //If the block you're currently looking at is free and either the same or larger size than the incoming block,
    //then split the block and take up the block and have a free block
    if(currentBlock -> occ == 0){
      if(currentBlock -> size  >= newBlock -> size){
        //If the incoming block and the free block are the same size, just fill it in
        if(currentBlock -> size == newBlock -> size){
          currentBlock -> occ = 1;
          int removeExtra = 0 - newBlock -> size;
          sbrk(removeExtra);
          return currentBlock + sizeof(struct Block);
        }
        //If they're bigger sizes, split it into 2 blocks and fill 1 in. Must also leave room for another block to the right
        else if(currentBlock -> size >= newBlock -> size + sizeof(struct Block)){
          //Set the integer to 1 to denote that there is a place for it to go if no blocks match size
          bestFit = 1;
          //Save the block in which it would fit best if no blocks match size
          if(bestFitBlock == NULL){
            bestFitBlock = currentBlock;
          }
          else if(currentBlock -> size > bestFitBlock -> size){
            bestFitBlock = currentBlock;
          }
        }
      }
    }
    //Go to the next block
    currentBlock = currentBlock -> next;
  }

  //Split the block into a taken and free slot
  if(bestFit == 1){
    currentBlock = bestFitBlock;
    int freeSize = currentBlock -> size - newBlock -> size;

    currentBlock -> occ = 1;
    currentBlock -> size = newBlock -> size;

    void *tempPointer = (int)currentBlock + (int)currentBlock -> size;
    struct Block *newFreeBlock = tempPointer;
    newFreeBlock -> occ = 0;
    newFreeBlock -> size = freeSize;
    newFreeBlock -> next = currentBlock -> next;
    newFreeBlock -> prev = currentBlock;
    newFreeBlock -> next -> prev = newFreeBlock;

    currentBlock -> next = newFreeBlock;

    //TROUBLESHOOTING: PRINT WHAT IS SUPPOSED TO BE RETURNED
    printf("%d ", (int)currentBlock + (int)sizeof(struct Block));

    int removeExtra = 0 - newBlock -> size;
    sbrk(removeExtra);
    return (int)currentBlock + (int)sizeof(struct Block);
  }

  if(head == NULL){
    head = newBlock;
  }
  else{
    currentBlock = head;
    while(currentBlock -> next != NULL){
      currentBlock = currentBlock -> next;
    }
    currentBlock -> next = newBlock;
    newBlock -> prev = currentBlock;
  }

  if(success == 0){
    return offset + sizeof(struct Block);
  }
  else{
    printf("Error - Malloc not completed\n");
    return (int *)-1;
  }
}


void my_free(void *data)
{
  struct Block *currentBlock = head;
  void *lookingFor = data - sizeof(struct Block);
  while(lookingFor != currentBlock){
    currentBlock = currentBlock -> next;
  }
  currentBlock -> occ = 0;


  //If the block after the one being freed is empty, coalesce these two together
  if(currentBlock -> next != NULL && currentBlock -> next -> occ == 0){
    currentBlock -> size = currentBlock -> size + currentBlock -> next -> size;
    currentBlock -> next = currentBlock -> next -> next;
    if(currentBlock -> next != NULL){
      struct Block *tempBlock = currentBlock -> next;
      tempBlock -> prev = currentBlock;
    }
  }

  //If the block before the one being freed is empty, change the current block to the previous one
  //and do the same procedure as above to coalesce the two together
  if(currentBlock != head && currentBlock -> prev -> occ == 0){
    currentBlock = currentBlock -> prev;
    currentBlock -> size = currentBlock -> size + currentBlock -> next -> size;
    currentBlock -> next = currentBlock -> next -> next;
    if(currentBlock -> next != NULL){
      currentBlock -> next -> prev = currentBlock;
    }
  }

  //If the free block is next to the end of the heap, decrease the size of the heap
  //by disbanding the last block
  if(currentBlock -> next == NULL){
    int sizeDecrease = 0 - currentBlock -> size;
    sbrk(sizeDecrease);
    if(currentBlock == head){
      brk(head);
      head = NULL;
    }
    else{
      currentBlock -> prev -> next == NULL;
    }
  }
}

и моя программа тестирования:

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

void *my_malloc(int size);
void my_free(void *data);

//include your code


//replace malloc here with the appropriate version of my_malloc
#define MALLOC my_malloc
//replace free here with the appropriate version of my_free
#define FREE my_free
//define DUMP_HEAP() to be dump_heap() when you are done
#define DUMP_HEAP()

int main()
{
  char *dummy = MALLOC(23 + 24 * 5);
  FREE(dummy);
  DUMP_HEAP();

  char *this = MALLOC(5);
  char *is = MALLOC(3);
  char *a = MALLOC(2);
  char *test = MALLOC(5);
  char *program = MALLOC(8);
  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();

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

  FREE(this);
  printf("%s %s %s %s %s\n", "*", "*", a, "*", program);
  DUMP_HEAP();

  this = MALLOC(5);
//TROUBLESHOOTING: PRINT WHAT'S ACTUALLY BEING RETURNED
printf("%d ", (char *)this);
  strcpy(this, "this");
  printf("%s %s %s %s %s\n", this, "*", a, "*", program);
  DUMP_HEAP();

  is = MALLOC(3);
  test = MALLOC(5);
//MORE TROUBLESHOOTING
printf("%d ", (char *)test);
  strcpy(is, "is");
  strcpy(test, "test");
  printf("%s %s %s %s %s\n", this, is, a, test, program);
  DUMP_HEAP();

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

  return 0;
}

Проблема, с которой я столкнулся, связана с ошибкой сегмента, когда строка FREE (this) запускается в конце программы. Я предполагаю, что это из-за неправильного указателя, возвращаемого из моей функции my_malloc. Я прошу прощения за то, что код не является очень кратким, заранее спасибо за любую помощь!

...