如何正确替换动态分配的 C 数组中的日期

How to properly replace day in a dynamically allocated C array

我正在研究一个使用 C 语言动态分配数组的基本框架。我创建了一个函数来创建标题为 init_string_vector 的字符串数组。可以使用 append_string_vector 函数将数据附加到数组,并且可以使用 free_string_array 函数从堆中 de-allocated 获取数据。我目前正在开发一个名为 replace_string_vector_index 的函数,它允许用户将数组索引以及指向字符串数组的指针传递给该函数。如果数组类型为 STRING 数组且索引未超出范围,则函数应将现有数据替换为用户传递给函数的字符串。

replace_string_vector_index 函数似乎工作正常,确实将索引处的字符串替换为用户传递给该函数的其他字符串。但是,一旦我习惯了 replace_string_vector_index 函数作用于数组,free_string_array 函数就不再起作用了。这让我认为函数内的过程导致了问题,但我看不出是如何造成的。一个例子如下所示。当 free_string_array 函数失败时,我得到以下错误,free(): invalid pointer

vector.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[]);
// --------------------------------------------------------------------------------

vector.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);
}

如果我理解你的 replace_string_vector_index 函数的要求,你应该首先释放 array->array[index] 的内存,然后将 strdup(string) 的结果分配给该元素。

无需转换,无需复杂的指针运算。只是简单地:

free(array->array[index]);
array->array[index] = strdup(string);

现在发生的事情(我认为)是你让 array->array[index] 指向包含字符串的 array(即你忘记了 strdup 步骤). malloc 未分配且无法传递给 free.

的数组

因为您将把它作为 free_string_array 的一部分传递给 free,您将有 未定义的行为