如何正确替换动态分配的 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
,您将有 未定义的行为。
我正在研究一个使用 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
,您将有 未定义的行为。