您遇到的一个问题是您对动态分配的内存可以扩展(或为此使用)什么有基本的了解。您的 typedef 结构 Array 是 固定大小。如果您分配给Array *array,则此后您不能将realloc 分配给array。它将永远是sizeof *array。为它分配更多内存没有好处,因为它不包含指向任何额外内存的指针,并且会破坏类型的指针算术。
您唯一能做的就是分配Array 的任何数组。但这会比较麻烦,因为每个元素最多只能存储 DEFAULT_SIZE 令牌。
如果我了解您要完成的工作,而不是让您的结构包含固定大小的二维数组 pointer,您需要 pointer 实际上是一个 指向数组的指针 char[256] 的 em>。例如,你想要:
#define DEFAULT_SIZE 3 /* default size of an array of words */
#define TOKEN_SIZE 256
typedef struct {
char (*pointer)[TOKEN_SIZE];
int used;
int size;
} arr;
(注意: C 避免使用camelCase 或PascalCase 变量名,而保留大写所有小写 /em> 用于宏和常量的名称。)
现在,您确实可以在Array 中调整大小(标准情况下是我的arr)。您可以分配arr 的实例,然后为arr->pointer 分配(和realloc arr->pointer arr->used >= arr->size 时)
重做您的示例,为每个内存分配添加适当的验证,并使用realloc 方案,每次arr->used >= arr->size 将realloc arr->pointer 到2 * arr->size,您可以这样做类似于以下内容:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEFAULT_SIZE 3 /* default size of an array of words */
#define TOKEN_SIZE 256
typedef struct {
char (*pointer)[TOKEN_SIZE];
int used;
int size;
} arr;
arr *createArray (int start_size)
{
arr *array = malloc (sizeof *array);
if (!array) {
perror ("malloc - array");
exit (EXIT_FAILURE);
}
array->used = 0;
array->size = start_size;
array->pointer = malloc (start_size * sizeof *array->pointer);
if (!array->pointer) {
perror ("malloc - array->pointer");
exit (EXIT_FAILURE);
}
return array;
}
void append (arr *array, char *elem)
{
if (array->used >= array->size) {
void *tmp = realloc (array->pointer, array->size * 2 * sizeof *array->pointer);
if (!tmp) {
perror ("realloc - array->pointer");
return; /* you should change function type provide success/failure */
}
array->pointer = tmp;
array->size *= 2; /* update size */
}
if (strlen (elem) + 1 < sizeof *array->pointer) {
strcpy (array->pointer[array->used], elem); // insert new element
array->used++; // <-- wrong value here. increment info about used slots
}
else
fprintf (stderr, "error: token too long.\n");
}
arr *parse (char* command)
{
char *args_str;
arr *args_list = createArray (DEFAULT_SIZE);
args_str = strtok (command, " ");
while (args_str != NULL) {
append (args_list, args_str);
args_str = strtok (NULL, " ");
}
return args_list;
}
/* simple print function */
void prnarr (arr *array)
{
int i;
for (i = 0; i < array->used; i++)
printf ("array[%2d] : %s\n", i, array->pointer[i]);
}
/* simple function to free allocated memory */
void freearr (arr *array)
{
free (array->pointer);
free (array);
}
int main (void) {
char str[] = "my dog has fleas my cat has none lucky cat";
arr *args = parse (str);
prnarr (args);
freearr (args);
return 0;
}
使用/输出示例
$ ./bin/arr_struct_arr_of_ptrs
array[ 0] : my
array[ 1] : dog
array[ 2] : has
array[ 3] : fleas
array[ 4] : my
array[ 5] : cat
array[ 6] : has
array[ 7] : none
array[ 8] : lucky
array[ 9] : cat
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此 (2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。
对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/arr_struct_arr_of_ptrs
==9128== Memcheck, a memory error detector
==9128== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9128== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9128== Command: ./bin/arr_struct_arr_of_ptrs
==9128==
array[ 0] : my
array[ 1] : dog
array[ 2] : has
array[ 3] : fleas
array[ 4] : my
array[ 5] : cat
array[ 6] : has
array[ 7] : none
array[ 8] : lucky
array[ 9] : cat
==9128==
==9128== HEAP SUMMARY:
==9128== in use at exit: 0 bytes in 0 blocks
==9128== total heap usage: 4 allocs, 4 frees, 5,392 bytes allocated
==9128==
==9128== All heap blocks were freed -- no leaks are possible
==9128==
==9128== For counts of detected and suppressed errors, rerun with: -v
==9128== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放已分配的所有内存并且没有内存错误。
查看一下,如果您还有其他问题,请告诉我。