Search code examples
cmemory-managementglibc

Dynamic Memory Deallocation in C


I have these 2 structures and 4 constants:

#define MAX_BLK 16
#define MAX_STR 32
#define C_TRUE  1
#define C_FALSE 0

typedef struct {
  int  rsv;
  void *addr;
  int   size;
  char  tag[MAX_STR];
} BlockType;

typedef struct {
  int numBlocks;
  BlockType *blocks;
} HeapType;

Here is my function for initializing a heap structure:

void mh_init(HeapType *heap) {
  heap->numBlocks = 0;
  heap->blocks = (BlockType *) malloc(sizeof(BlockType[MAX_BLK]));
}

Here is my function for allocating a new block (creates a block of n bytes, adds new block and info to heap->blocks array, then returns pointer of new block of memory):

void *mh_alloc(HeapType *heap, int n, char *label) {
  void *newAddr = (void*) malloc(n);
  heap->blocks[heap->numBlocks].addr = newAddr;
  heap->blocks[heap->numBlocks].rsv = C_TRUE;
  heap->blocks[heap->numBlocks].size = n;
  strcpy(heap->blocks[heap->numBlocks].tag, label);
  heap->numBlocks += 1;
  return newAddr;
}

And then in the end, free every block and the heap structure:

void mh_cleanup(HeapType *heap) {
  for (int i = 0; i < heap->numBlocks; i++) {
    printf("block %d\n", i);
    free_block(&heap->blocks[i]);
  }
  free(&heap->numBlocks);
  free(heap->blocks);
}

void free_block(BlockType *block) {
  free(&(block->rsv));
  printf(" freed: rsv,");
  if (block->addr != NULL) { free(block->addr);  }
  printf("adr, ");
  free(&(block->size));
  printf("size, ");
  free(block->tag);
  printf("tag\n");
}

Everything compiles fine but when I run I keep getting a glibc error : "* glibc detected * ./a3: free(): invalid pointer: 0x002b6470 ***"

I've done an hour or so of research and think this error means I'm passing an invalid address to free(). Basically it prints out block 0, frees rsv, but then nothing else. Can anyone tell me where I'm going wrong with my approach??

***Note there is other parts to my program but don't think they are significant for this question


Solution

  • This looks really suspicious:

      free(&(block->rsv));
    

    You should only be passing pointers to free that you got from malloc. In this case, you're passing a pointer to an int in a structure you allocated. If you are operating on the second structure in the array you allocated, this certainly isn't a pointer you got from malloc. If it's the first element, this might deallocate the whole array if this is the same as the pointer to the array (not sure if that's guaranteed), in which case the rest of the function is operating on free'd memory, which is very bad.