tags:

views:

155

answers:

3

I have structs like this:

struct Child
{
  int foo;
  char bar[42];
};

struct Parent
{
   long foobar;
   struct Child ** children;
   size_t num_children;
}

I have defined an API like this:

struct Parent * ParentAlloc() { struct Parent* ptr = (struct Parent*)calloc(1, sizeof(struct Parent));
ptr->children = (struct Child**)calloc(SOME_NUMBER, sizeof(struct Child*));
return ptr;
}

Now, if I want to delete a (previously allocated) child - assuming index is not out of bounds:

void FreeChild(struct Parent* parent, const size_t index)
{
   free(parent->children[index]);

   //now I want to mark the address pointed to in the array of pointers as null, to mark it as available

   //I dont think I can do this (next line), since I have freed the pointer (its now "dangling")
   parent->children[index] = 0; // this is not right. How do I set this 'freed' address to null ?


}
+2  A: 

There is no problem with setting the parent->children[index] to NULL. You only freed the memory where the pointer points to, not the memory where the pointer itself is stored.

swegi
A: 

You are mixing array of pointers with array of structures. Remove double star and operate on offsets:


...
struct Parent
{
  long foobar;
  struct Child* kids;
  size_t numkids;
};
...
struct Parent * ParentAlloc()
{
  struct Parent* ptr = ( struct Parent* )calloc( 1, sizeof( struct Parent ));
  ptr->kids = ( struct Child* )calloc( SOME_NUMBER, sizeof( struct Child ));
  ptr->numkids = SOME_NUMBER; /* don't forget this! */
  return ptr;
}
...
struct Child* GetChild( struct Parent* p, size_t index )
{
  assert( p );
  assert( index < p->numkids );
  return p->kids + index;
}
Nikolai N Fetissov
Thanks - much cleaner than my original code (though I am assured that it was ok, I was getting myself confused because I was mixing array of ptrs and array of structs). Thanks to all who answered. much obliged
scoobydoo
+2  A: 

Of course you can do this. A pointer is a variable whose value is an address. It's perfectly okay, actually good practice, to set pointers to 0 (or NULL) after calling free, so that you can check them for being non-null and avoid segfaults. Bottom line: Your code is okay.

Christian