Я пытаюсь создать вектор в 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);
}
Этот код очень неполный - например, что такое vect_t
У вас есть функция удаления, но вызываете ли вы ее на самом деле?
Если вам нужно привести результат malloc, вы компилируете код C с помощью компилятора C++, и это неправильно.
PSA: если вы делаете много сложных распределений, рассмотрите calloc()
, которое дает понять, что и сколько вы распределяете очень последовательным образом. Кроме того, нет необходимости преобразовывать результат распределения в C.
vect_t *vect_new()
в C++ это нормально, в C нет. vect_t *vect_new(void)
@tadman да, я называл это в своих тестах.
покажи как ты это называешь
v->data = malloc(...)
но нет соответствующего free(v->data)
. Кроме того: если первый malloc проходит, а второй терпит неудачу, у вас есть утечка памяти (вероятно, в этот момент это не имеет значения, но все же...)
Покажите, как вы выделяете память для жал
VECT_INITIAL_CAPACITY
«НАЧАЛЬНОЕ» предполагает, что вы можете realloc()
в какой-то момент... Пожалуйста, поймите, что realloc()
в функции «добавить в коллекцию» может справиться (очень хорошо) с начальным распределением, которое равно нулю... Подумайте об этом...
@0___________ Я добавил к своему вопросу
Я заметил выделение памяти для «v-> data» на основе «VECT_INITIAL_CAPACITY», но в вашей функции очистки вы используете элемент «v-> size» в цикле for для освобождения данных. Если это значение никогда не меняется с нуля, я не вижу, чтобы вызов free когда-либо происходил. Следует ли вам использовать v->capacity?
/** 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);
}
}
Некоторые замечания:
size_t
), а не int
или unsigned
sizeof
s. vect_t *v = malloc(sizeof(*v));
void *
, например malloc
. Если код не компилируется, то вы используете неправильный компилятор (C++) для компиляции кода C.Кстати, хорошее использование if (v)
. Упрощает обязанности вызывающего вызывающего кода.
Могу ли я спросить, зачем иметь free(v->data) после цикла for?
@d0nut, потому что вы выделяете для него память
В дополнение к @0___________ хороший ответ,
if (v->data == NULL) { return NULL; }
тоже протекает.
Используйте if (v->data == NULL) { free(v); return NULL; }
.
Вы не показываете код очистки, поэтому вам нужно опубликовать его. Помните, что все, что было возвращено из
malloc
, должно быть переданоfree
для очистки.