Каков наилучший способ разрушить структуру в C

В C++ у нас есть структуры, в которых есть конструктор и деструктор. Это значительно облегчает жизнь, особенно когда она имеет указатели, поэтому динамически распределяет память в структуре. Вы даже можете использовать библиотеку std::shared_pointer для работы с указателями.

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

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

Но мой лектор по математике не любит C++ и предпочитает все на C. Поэтому мне пришлось использовать C вместо этого и придумал следующую структуру:

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

Я составил функцию, которая вычисляет медиану вектора двойников.

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
}

В качестве примера плохих практик я не освободил память. Когда функция возвращает свое значение, она разрушает локальные переменные и структуры. Но моя структура имеет указатель, который содержит выделенную память. Вряд ли после некоторого исследования в интернете я не нашел ни одного хорошего метода разрушения для этих ситуаций.

Мой вопрос заключается в том, как старомодные программисты на Си имели дело с такими ситуациями, когда они хотят освободить указатели в структуре, но у них нет деструктора для структуры, который выполнялся бы для выполнения определенной работы?

3 ответа

Решение

Простой указатель нуждается в *alloc() и, наконец, free(),

Структура с динамическими полями заслуживает vector_alloc() а также vector_free(),

Старый школьный ароматизированный результат:

// 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;
}

Если вы хотите освободить объект, который использует какое-то иерархическое хранилище (то есть внутренние указатели на другой объект) в C, я обычно пишу свободную функцию, специфичную для этого объекта. Например:

void free_my_obj(my_obj_t *my_obj)
{
    free(my_obj->a);
    free_my_obj2(my_obj->my_obj2);
    free(my_obj);
}

В начале: n.stack=…malloc();

В конце: free(n.stack);

Каждый malloc() в начале блока должен иметь соответствующий free(); ближний конец блока

Другие вопросы по тегам