0

I would like to get a reference to an element at position in an array of void pointers. This is my function, I don't know if am doing it correctly. I have these two functions:

typedef struct vector 
{
  void **array;
  size_t size;
}vector;

I believe this gets the reference to the element at position pos.

void **get_at(vector *this, size_t pos) 
{
   assert(pos >=0 && pos < this->size);

   return &this->array[pos];
}

I believe this gets the pointer to the element at position pos.

void *at(vector *this, size_t pos) 
{
   assert(pos >=0 && pos < this->size);

   return this->array[pos];
}

I just would like to know if am correct with this implementation.

Just one more question: If I want to destroy the array, is doing it this way enough? Do I have to loop through the array elements freeing the memory held by each element?

void destroy(vector *this)
{
  free(this->array);
  free(this);
}
1
  • 1
    Functions "get_at" and "at" look OK to me, but destroy needs to make sure all the void pointers in the this->array are disposed properly: first "free" each one of them, and then free "this" Commented Dec 10, 2022 at 11:20

1 Answer 1

1

Do I have to loop through the array elements freeing the memory held by each element?

This is something only you can know.

There is a notion of ownership that is pervasive in all languages that support manual memory management. Every object is owned by some other object (or maybe by a group of objects but that's a bit more involved). When the owner dies, all objects owned by it die too.

We tend to personify the objects a bit, so you will often hear questions like "who owns this?". This "who" refers to an object, not to a person.

You have a vector of pointers that point to a bunch of objects. Who owns these objects? This is up to you to decide.

If the vector itself is the owner, then it will be a good idea to free the objects when the array itself is freed. Note that freeing an object may be a bit more involved than just calling free() (just imagine that each of these objects is another vector). This is why a good vector would look something like this:

typedef struct vector 
{
  void **array;
  size_t size;
  void (*destroy)(void*); // call this for each object
                          // when freeing the vector
} vector;

You assign the destroy member when you initialise your vector.

Your destroy function would look like this:

void destroy(vector *this)
{
  if (this->destroy) 
    for (int i = 0; i < this->size; ++i) 
      this->destroy(this->array[i]);
  free(this->array);
  free(this);
}

If your vector doesn't own objects it points to, it shouldn't try to destroy them. This vector implementation works in this case too, just assign a null pointer to this->destroy.

You should design a coherent ownership structure for your program. There are no universal recipes.


get_at and at look OK as is.

Sign up to request clarification or add additional context in comments.

3 Comments

@Calvince please, consider accepting n.m.'s explanation as an answer to your question.
When I loop over the array of elements and try deleting each element, I get an error, munmap_chunk(): invalid pointer but if just call the free(this->array) it just works fine
@Calvince There is a bug in your program somewhere. My crystal ball is unfortunately out for maintenance, so I cannot tell you where exactly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.