Создание вектора приводит к утечке памяти в C

Я пытаюсь создать вектор в C, ниже приводится объявление структуры:

#define VECT_INITIAL_CAPACITY 4

typedef struct vect vect_t;

struct vect {
  char **data; // data is an array of strings             
  unsigned int size;      
  unsigned int capacity;   
}; 

У меня есть функция, которая создает новый пустой вектор, вот что я сделал:

vect_t *vect_new() {

  vect_t *v = (vect_t*) malloc(sizeof(vect_t));

  if (v == NULL) {
    return NULL;
  }

  // Allocate memory for data
  v->data = (char**) malloc(VECT_INITIAL_CAPACITY * sizeof(char*));
  if (v->data == NULL) {
    return NULL;
  }

  for (int i = 0; i < VECT_INITIAL_CAPACITY; i++) {
    v->data[i] = NULL;
  }

  // Initialize fields
  v->size = 0;
  v->capacity = VECT_INITIAL_CAPACITY;

  return v;
}

Valgrind говорит мне, что строка v->data = (char**) malloc(VECT_INITIAL_CAPACITY * sizeof(char*)); вызвала утечку памяти. Но я не уверен, как это исправить. Может ли кто-нибудь указать, что вызвало утечку памяти?

Обновлено: добавлен мой код очистки ниже:

/** Free all the memories of the vector. */
void vect_delete(vect_t *v) {

  // Delete data first
  for (int i = 0; i < v->size; i++) {
    free(v->data[i]);
  }
  // Delete the vector
  free(v);
}

Вы не показываете код очистки, поэтому вам нужно опубликовать его. Помните, что все, что было возвращено из malloc, должно быть передано free для очистки.

dbush 07.02.2023 04:13

Этот код очень неполный - например, что такое vect_t

0___________ 07.02.2023 04:15

У вас есть функция удаления, но вызываете ли вы ее на самом деле?

tadman 07.02.2023 04:16

Если вам нужно привести результат malloc, вы компилируете код C с помощью компилятора C++, и это неправильно.

0___________ 07.02.2023 04:16

PSA: если вы делаете много сложных распределений, рассмотрите calloc(), которое дает понять, что и сколько вы распределяете очень последовательным образом. Кроме того, нет необходимости преобразовывать результат распределения в C.

tadman 07.02.2023 04:17
vect_t *vect_new() в C++ это нормально, в C нет. vect_t *vect_new(void)
0___________ 07.02.2023 04:18

@tadman да, я называл это в своих тестах.

d0nut 07.02.2023 04:18

покажи как ты это называешь

0___________ 07.02.2023 04:21
v->data = malloc(...) но нет соответствующего free(v->data). Кроме того: если первый malloc проходит, а второй терпит неудачу, у вас есть утечка памяти (вероятно, в этот момент это не имеет значения, но все же...)
John3136 07.02.2023 04:21

Покажите, как вы выделяете память для жал

0___________ 07.02.2023 04:22
VECT_INITIAL_CAPACITY «НАЧАЛЬНОЕ» предполагает, что вы можете realloc() в какой-то момент... Пожалуйста, поймите, что realloc() в функции «добавить в коллекцию» может справиться (очень хорошо) с начальным распределением, которое равно нулю... Подумайте об этом...
Fe2O3 07.02.2023 04:31

@0___________ Я добавил к своему вопросу

d0nut 07.02.2023 04:35

Я заметил выделение памяти для «v-> data» на основе «VECT_INITIAL_CAPACITY», но в вашей функции очистки вы используете элемент «v-> size» в цикле for для освобождения данных. Если это значение никогда не меняется с нуля, я не вижу, чтобы вызов free когда-либо происходил. Следует ли вам использовать v->capacity?

NoDakker 07.02.2023 04:35
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
13
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
/** Delete the vector, freeing all memory it occupies. */
void vect_delete(vect_t *v) 
{
    if (v)
    {
        // Delete data first
        if (v -> data)
            for (size_t i = 0; i < v->capacity; i++)  //not v->size
            {
                free(v->data[i]);
            }
        free(v -> data);  //missing
        // Delete the vector
        free(v);
    }
}

Некоторые замечания:

  1. Используйте правильный тип для размеров и индексов (size_t), а не int или unsigned
  2. Используйте объекты вместо типов в sizeofs. vect_t *v = malloc(sizeof(*v));
  3. Не преобразовывайте результаты функций void *, например malloc. Если код не компилируется, то вы используете неправильный компилятор (C++) для компиляции кода C.

Кстати, хорошее использование if (v). Упрощает обязанности вызывающего вызывающего кода.

chux - Reinstate Monica 07.02.2023 04:53

Могу ли я спросить, зачем иметь free(v->data) после цикла for?

d0nut 07.02.2023 05:51

@d0nut, потому что вы выделяете для него память

0___________ 07.02.2023 10:52

В дополнение к @0___________ хороший ответ,

if (v->data == NULL) { return NULL; } тоже протекает.

Используйте if (v->data == NULL) { free(v); return NULL; }.

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