Search code examples
cpointersstructdestructordynamic-allocation

What is the best way to destruct the structure in C


In C++ we have structures which have a constructor and the destructor. It makes life much easier especially when it going to have the pointers, therefore dynamically allocated memory in the structure. You can even use std::shared_pointer library to deal with the pointers.

class A{
private:
    int size;
    double* stack;

public:    
   A(int size) : this->size(size){}
   ~A(){free(stack);}
};

But my maths lecturer doesn't like C++ and prefers everything in C. So I had to use C instead and came up with the following structure:

typedef struct vectorOfDoubles{
    double* stack;
    int size;
} vector;

I made up function that calculate the median of the vector of doubles.

double median_(const vector* v) {
    vector n;  // creates vector class object
    n.stack = (double*)malloc(sizeof(double)*(n.size = v->size));  // takes double ptr and allocates the right amount of memory for it
    memcpy(n.stack, v->stack, sizeof(double)*n.size);  // copies the array of doubles.
    sort(&n);  // sorts the array of doubles 
    if(v->size%2)  // checks for odd size
        return n.stack[(v->size/2+1)];  // return median for odd size
    else
        return (n.stack[(v->size/2)]+n.stack[(v->size/2+1)])/2;  // return median for even size
}

As an example of the bad practices I didn't free the memory. When the function returns its value it destructs the local variables and structures. But my structure has a pointer that holds the allocated memory. Unlikely after some research on the internet I didn't find any good destruction method solution for these situations.

My question is how the old-school C programmers dealt with those situations when they want to free the pointers in the structure but they do not have the destructor for structure that would execute itself to do a certain job?


Solution

  • A simple pointer needs a *alloc() and lastly a free().

    A structure with dynamic fields deserves a crafted vector_alloc() and vector_free().

    An old school flavored result:

    // Return non-0 on error
    int vector_alloc(vector *ptr, size_t size) {
      assert(ptr);
      ptr->stack = calloc(size, sizeof *(ptr->stack));
      if (ptr->stack) {
        ptr->size = size;
        return 0;
      }
      ptr->size = 0;
      return 1;
    }
    
    void vector_free(vector *ptr) {
      assert(ptr);
      free(ptr->stack);
      ptr->stack = NULL;
      ptr->size = 0;
    }
    
    
    double median_(const vector* v) {
        vector n;
        if (vector_alloc(&n, v->size)) return 0.0/0.0;
        memcpy(n, v->stack, sizeof *n->stack *n.size);
        sort(&n);  
        double y;   
        if(v->size%2) 
            y = n.stack[(v->size/2+1)];
        else
            y = (n.stack[(v->size/2)]+n.stack[(v->size/2+1)])/2;
        vector_free(&n);
        return y;
    }