C语言 我如何在一个结构中释放一个可增长的(使用realloc)动态数组?



在很长一段时间的休息之后,我重新访问了C语言,并且一直在专门利用可增长数组来帮助我回到手动内存管理。我使用的修改代码来自埃克塞特大学,并归功于埃克塞特大学)。

我试图在一个结构体中从一个(在这种情况下是整数)数组中释放单独分配的元素,但我在这样做时遇到了麻烦。

首先,我创建了一个结构体来保存一个整数数组、当前元素的数量和缓冲区大小,以跟踪已分配的内存。

typedef struct int_array
{
int *values;
int numValues;
int bufferLen;
} IntArray;

然后使用以下命令创建初始结构体:

IntArray *new_int_array(void)
{
IntArray *intArr;
intArr = calloc(1, sizeof *intArr);
intArr->bufferLen = intArr->numValues = 0;
intArr->values = NULL;
return intArr;
}

最后,向数组中添加元素:

void add_element_to_array(IntArray *intArr, int 
values)
{
// Check to see if array extension needed
if (intArr->numValues == intArr->bufferLen) {
intArr->bufferLen += GROWBY; // #define GROWBY 16
intArr->values = realloc
(intArr->values, intArr->bufferLen * 
sizeof intArr->values);
}
intArr->values[intArr->numValues] = 
values;
intArr->numValues++;
}

我习惯了释放一个单malloc/callloc数组,但是从我所读到的循环遍历所有元素并释放每个元素(每个分配一个自由)将是正确的方式,但我似乎不能得到它的权利。我正在调用一个辅助函数来释放内存:

void free_struct(IntArray *intArr)
{
for(int i = 0; i < intArr->bufferLen; i++){
free(intArr->values[i]);
}
}

我可以粘贴我在玩上面的free_struct函数时得到的许多错误,但我将永远在这里。它们的范围从期望void *到无效类型参数,到双自由度和其他。

编辑:我没有提到我所面临的最大问题,根据Valgrind的说法,那就是内存泄漏。被接受的答案解决了这个问题,因为正确地解引用intArr->values允许我释放相同的intArr->values,然后释放intArr本身。

这段代码在添加

时出现了一个问题
if (intArr->numValues == intArr->bufferLen) {
intArr->bufferLen += GROWBY; // #define GROWBY 16
intArr->values = realloc
(intArr->values, intArr->bufferLen *
sizeof intArr->values);
}

这是解决问题的方法:

if( arr->nVal == arr->bufLen) {
arr->bufLen += GROWBY; // #define GROWBY 16
arr->vals = realloc( arr->vals, arr->bufLen * sizeof *arr->vals );
// NOTICE    ^
}

OP代码在表达式的sizeof项中缺少解引用星号。

请注意,当涉及语句没有分布在多行源代码中时,这是多么容易阅读。我建议使用有意义但简短的变量名。源代码需要是"可扫描的",而不是"在冬天的晚上在火炉旁可读的"。

注意,元素的大小是整数的大小,而不是指针的大小。当存储的整数变为存储的结构体时,这一点将变得非常重要。

alloc家族在任务中失败时,通常没有其他选择,只能优雅地退出。使用NULL指针继续处理(直到崩溃)是不合适的。

if( arr->nVal == arr->bufLen) {
arr->bufLen += GROWBY; // #define GROWBY 16
arr->vals = realloc( arr->vals, arr->bufLen * sizeof *arr->vals );
if( arr->vals == NULL ) {
fprintf( stderr, "realloc() failuren" );
exit( 1 );
}
}

现在这个问题已经解决了,'free() '问题应该更容易理解了。

指向数组的指针指向一个连续的内存块。你只需要一个free( arr->vals );来释放整个块。

当这个以GROWBY的增量"增长"数组时,你可能想要尝试删除一个随机元素(包括将数组中的后续元素向上移动;见memmove()),甚至收缩数组(再次realloc()),当有SHRINKBY未使用的元素在数组的底部…

编辑:
由于calloc()保证分配的字节将被设置为0,因此:

IntArray *new_int_array(void)
{
IntArray *intArr;
intArr = calloc(1, sizeof *intArr);
intArr->bufferLen = intArr->numValues = 0;
intArr->values = NULL;
return intArr;
}

可以简化为:

IntArray *new_int_array(void)
{
IntArray *arr = calloc(1, sizeof *arr);
if( arr == NULL ) {
fprintf( stderr, "calloc() failedn" );
exit( 1 );
}
return arr;
}

最新更新