Я работаю над базовой структурой для динамического выделения массива с помощью языка C. Я создал функцию для создания массива строк под названием init_string_vector
. Данные могут быть добавлены в массив с помощью функции append_string_vector
, а данные могут быть удалены из кучи с помощью функции free_string_array
. В настоящее время я работаю над функцией под названием replace_string_vector_index
, которая позволяет пользователю передавать индекс массива в функцию, а также указатель на массив строк. Если массив типизирован как массив STRING
и индекс не выходит за пределы, функция должна заменить существующие данные строкой, которую пользователь передает функции.
Функция replace_string_vector_index
работает правильно и заменяет строку в индексе другой строкой, которую пользователь передал функции. Однако функция free_string_array
больше не работает после того, как я использовал функцию replace_string_vector_index
для работы с массивом. Это заставляет меня думать, что процесс внутри функции вызывает проблему, но я не могу понять, как это сделать. Пример показан ниже. Когда функция free_string_array
дает сбой, я получаю следующую ошибку: free(): invalid pointer
.
вектор.h
#ifndef ARRAY_H
#define ARRAY_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef enum
{
FLOAT,
DOUBLE,
CHAR,
INT,
STRING
} dat_type;
// --------------------------------------------------------------------------------
typedef struct
{
char **array;
size_t len;
int elem;
dat_type dat;
} StringVector;
// --------------------------------------------------------------------------------
int string_vector_mem_alloc(StringVector *array, size_t num_indices);
// --------------------------------------------------------------------------------
StringVector init_string_vector();
// --------------------------------------------------------------------------------
int append_string_vector(StringVector *s, char *value);
// --------------------------------------------------------------------------------
void free_string_array(StringVector *array);
// --------------------------------------------------------------------------------
int replace_string_vector_index(StringVector *array, int index, char string[]);
// --------------------------------------------------------------------------------
вектор.c
#include "vector.h"
int string_vector_mem_alloc(StringVector *array, size_t num_indices) {
// Determine the total memory allocation and assign to pointer
void *pointer;
pointer = malloc(num_indices * array->elem);
// If memory is full fail gracefully
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
free(pointer);
return 0;
}
// Allocate resources and instantiate Array
else {
array->array = pointer;
array->len = 0;
return 1;
}
}
// --------------------------------------------------------------------------------
StringVector init_string_vector() {
StringVector array;
array.dat = STRING;
array.elem = sizeof(char *);
string_vector_mem_alloc(&array, array.elem);
return array;
}
// --------------------------------------------------------------------------------
int append_string_vector(StringVector *array, char *value) {
value = strdup(value);
if (!value) {
return -1;
}
array->len++;
char **resized = realloc(array->array, sizeof(char *)*array->len + 1);
if (!resized) {
free(value);
return -1;
}
resized[array->len-1] = value;
array->array = resized;
return 0;
}
// --------------------------------------------------------------------------------
void free_string_array(StringVector *array) {
if (array != NULL) {
for (int i = 0; i < array->len; i++) {
free(array->array[i]);
}
}
free(array->array);
// Reset all variables in the struct
array->array = NULL;
array->len = 0;
array->elem = 0;
}
// --------------------------------------------------------------------------------
int replace_string_vector_index(StringVector *array, int index, char string[]) {
if (array->dat != STRING) {
printf("Array data type must be a STRING");
return 0;
}
if (index > array->len) {
printf("Index is greater than array length");
return 0;
}
* (char **) ((char *) array->array + index * array->elem) = string;
return 1;
}
// --------------------------------------------------------------------------------
main.c
#include <stdio.h>
#include "vector.h"
int main(int argc, const char * argv[]) {
StringVector arr_test = init_string_vector();
char one[] = "Hello";
char two[] = "World";
char three[] = "Hello";
char four[] = "Goodbye";
append_string_vector(&arr_test, one);
append_string_vector(&arr_test, two);
append_string_vector(&arr_test, three);
append_string_vector(&arr_test, four);
// I can free the array at this point
free_string_array(&arr_test)
StringVector arr_test = init_string_vector();
append_string_vector(&arr_test, one);
append_string_vector(&arr_test, two);
append_string_vector(&arr_test, three);
append_string_vector(&arr_test, four);
replace_string_vector_index(&arr_test, 1, one);
// - Once I envoke replace_string_vector_index, free_string_array
// no longer works, and I get an invalid pointer error.
free_string_array(&arr_test);
}
🤔 А знаете ли вы, что...
C имеет богатую стандартную библиотеку, включающую функции для работы с файлами, строками, памятью и другими задачами.
Если я понимаю требования к вашей функции replace_string_vector_index
, вы должны сначала освободить память array->array[index]
, а затем присвоить результат strdup(string)
этому элементу.
Нет необходимости в приведении, нет сложной арифметики указателей. Просто:
free(array->array[index]);
array->array[index] = strdup(string);
Теперь (я думаю) происходит то, что вы указываете array->array[index]
на множество, который содержит строку (т. е. вы забываете шаг strdup
). Массив, который не был выделен malloc
и который не может быть передан free
.
Поскольку вы передадите его free
как часть free_string_array
, у вас будет неопределенное поведение.