在中断了很长一段时间后,我重新访问了C语言,并且一直在使用可增长数组来帮助我回到手动内存管理。我使用了University of Exeter中的修改代码。
我试图从结构体中的数组(在本例中为整数)中释放单独分配的元素,但是在这样做时遇到了麻烦。
首先,我创建一个结构体来保存一个整数数组、当前的元素数和缓冲区大小,以便跟踪分配的内存。
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/calloc数组,但是根据我所读到的,循环遍历所有元素并释放每个元素(每次分配释放一个元素)是正确的方法,但是我似乎不能正确地做到这一点,我调用一个helper函数来释放内存:
void free_struct(IntArray *intArr)
{
for(int i = 0; i < intArr->bufferLen; i++){
free(intArr->values[i]);
}
}
我可以粘贴我在使用上面的free_struct函数时遇到的许多错误,但我会永远呆在这里,它们的范围从期待void * 到无效类型参数,到double frees和其他类似的错误。
**编辑:**我忽略了提到我所面临的最大问题,根据Valgrind的说法,这是一个内存泄漏。公认的答案解决了这个问题,因为正确地解引用intArr->values
允许我释放相同的intArr->values
,然后释放intArr
本身。
1条答案
按热度按时间1mrurvl11#
添加以下内容时此代码中存在问题:
这是在修复的路上:
OP代码在表达式的
sizeof
项中缺少解引用星号。请注意,当一个 * involved * 语句没有分布在多行源代码中时,这是多么容易阅读。我建议使用有意义但简短的变量名。源代码需要是"可扫描的",而不是"在冬天晚上的炉火旁可读的"。
注意,元素的大小是整数的大小,而不是指针的大小。当存储的整数变成存储的结构体时,这一点就变得很重要了。
当
alloc
系列在任务中失败时,通常别无选择,只能优雅地退出。使用NULL指针继续处理(直到崩溃)是不优雅的。既然已经澄清了这个问题,那么"free()"问题应该更容易理解了。
指向数组的一个指针指向一个连续的内存块。您只需要一个
free( arr->vals );
就可以释放整个内存块。当数组以
GROWBY
为增量"增长"时,您可能希望尝试删除一个随机元素(包括在数组中向上移动后续元素;参见memmove()
),甚至当数组底部有SHRINKBY
个未使用的元素时缩小数组(再次为realloc()
)...由于
calloc()
保证分配的字节将被设置为0,因此:可简化为: