-1

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

PenguinProgrammer
  • 141
  • 2
  • 5
  • 11
  • In this sort of case, you can use a debugger or something like valgrind to see where and when in the execution the invalid free occurs. – Dettorer Oct 29 '14 at 14:42
  • Valgrind only tells me the method the free() error occurs in but nothing much more helpful. I've been trying to find where the problem is for hours and hours, it isn't obvious to me anyway – PenguinProgrammer Oct 29 '14 at 14:47
  • Ok, try a debugger then (gdb for example), when the invalid free occurs, you can see the whole call stack, the value of the pointer you tried to free etc. – Dettorer Oct 29 '14 at 14:49
  • [Don't cast the return value of `malloc()` in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Casting *to* `void *` was new to me, even! Don't do it. :) – unwind Oct 29 '14 at 14:49
  • i took a glance, and saw `free(&heap->numBlocks);free(heap->blocks);`. what does that mean? i am pretty sure you don't want to do that. – Jason Hu Oct 29 '14 at 14:50

1 Answers1

2

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.

Samuel Edwin Ward
  • 6,526
  • 3
  • 34
  • 62