CodingLab
CodingLab

Reputation: 1519

Is it OK to free 'void*'?

Consider:

struct foo
{
    int a;
    int b;
};

void* p = (void*)malloc(sizeof(struct foo));
((foo*)p)->a; // Do something.
free(p); // Is this safe?

Upvotes: 38

Views: 32670

Answers (8)

Malcolm McLean
Malcolm McLean

Reputation: 6404

Yes, but normally it's a sign of poor design.

malloc() is typically used to allocate buffers (large arrays of the same primitive type) or objects (structs with fields initialised). In both cases, the malloc and the free should match so,

  unsigned char *rgba_buffer = malloc(width * height * 4);
  /* Use the buffer here */
  free(rgba_buffer);

  BITSTREAM *bs = bitstream("bitfile.boin");
  /* Use the bitstream here */
  destroy_bitstream(bs);

  typedef struct
  {
     FILE *fp;
     unsigned char ch;
     int index;
  } BITSTREAM;


  BITSTREAM *bitstream(const char *filename)
  {
      BITSTREAM *bs = malloc(sizeof(BITSTREAM));
      bs->fp = fopen(filename "rb");
      /* etc */
      return bs;
  }

  void destroybitstream(BITSTREAM *bs)
  {
     if(bs)
     {
        if(bs->fp)
          fclose(bs->fp);
        free(bs);
     }
  }

In one case, malloc and free match, and in the other the allocated memory is returned. There are also secondary resources, and the constructor and destructor match. It should be rare to allocate a region of memory, but not know what it is used for. And you shouldn't be interleaving allocations and frees chaotically.

Modern C++ tightens this all up with unique pointers which "own" the object. While you can have a unique pointer to void, it would be very rare.

Upvotes: 0

matt
matt

Reputation: 4244

In C it is perfectly safe, because there are no destructors to call.

The memory system keeps track of the size of allocations.

In C++ you must delete the same type you new, including using the delete[] operator to delete new'ed arrays.

This is just to make sure destructors are called.

Upvotes: 4

Laurence Gonsalves
Laurence Gonsalves

Reputation: 143234

Yes.

malloc returns void * and free takes void *, so some of your casts are meaningless, and you're always freeing a void * even if you're starting with some other sort of pointer.

Upvotes: 49

rickmode
rickmode

Reputation: 115

Perhaps it doesn't feel safe because of the magic happening behind the scenes. The C runtime and/or the OS itself is actively tracking the memory returned by malloc including its size and location. See though it feels like you are passing a typeless pointer back to free(), you in fact passing back a reference to an object the memory manager is actively tracking.

Upvotes: 2

Pepor
Pepor

Reputation: 1072

Yes, it's safe. When allocating memory, the runtime library keeps track of the size of each allocation. When you call free(), it looks up the address, and if it finds an allocation for that address, the correct amount of memory is freed (the block that was allocated at that address).

Upvotes: 20

jamesdlin
jamesdlin

Reputation: 90025

Yes. The function prototype for free is even:

void free(void *ptr);

Upvotes: 3

Jerry Coffin
Jerry Coffin

Reputation: 490218

Yes -- free takes a pointer to void, so when you call it, the pointer is (implicitly) cast to a pointer to void in any case.

The rest of your code isn't quite so safe:

void* p = (void*)malloc(sizeof(foo));

You should not cast the return from malloc (in C). This can cover up the mistake of forgetting to #include <stdlib.h>

Upvotes: 7

Hogan
Hogan

Reputation: 70523

yes it is safe.

Upvotes: 0

Related Questions