我有以下功能:
void deleteInventory( struct book** inventory )
{
struct book* ptr = NULL;
ptr = *inventory;
while( length != 0)
{
free(ptr);
length--;
++ptr;
}
free(inventory);
}
结构:
#define MAX_LENGTH 64
#define ISBN_LENGTH 11
struct book
{
char isbn[ISBN_LENGTH];
char title[MAX_LENGTH];
char author[MAX_LENGTH];
int year;
float price;
};
结构总大小: 147字节(11 + 64 + 64 + 4 + 4) sizeof(struct book)返回: 148字节
我的库存变量是结构数组,包含3条记录
现在,函数调试的结果(没有高2字节的地址):
inventory[0] = 0x1350
inventory[1] = 0x14e0
inventory[2] = 0x1670
内存差异:400字节,确定
在第一次迭代时,一切正常,首先记录删除没有问题
但
之后++ptr;
ptr将包含: 0x13e4
库存[0] - ptr = 148字节 - 根据结构大小纠正差异
但它没有引用下一条记录,因为内存中的下一条记录的地址: 0x14e0 而且我的堆已经损坏了。
任何建议:为什么?
答案 0 :(得分:7)
你说inventory
是一个数组,没关系。
你已经说book
占用了148个字节(当你计算填充时),这很好。
你没有说的是你在inventory
中放置的指针是一次性分配的,而且你有一个指针数组的事实意味着他们不是。
但是你创建了每个book
,它似乎是动态的。不能保证这些书是连续的,只是指向它们的指针。
更改您的功能:
void deleteInventory( struct book** inventory )
{
struct book* ptr = NULL;
for (int i = 0; i < length; ++i) {
ptr = inventory[i];
free(ptr);
}
length = 0;
free(inventory);
}
这将读取连续的指针到book
数组以删除所有book
,而不假设book
本身是连续分配的。
答案 1 :(得分:6)
我认为您正在从inventory
错误地删除。在free(ptr)
之后,ptr
之后的下一个内存块可能是垃圾内存。我认为这是删除库存的正确方法:
void deleteInventory( struct book** inventory )
{
book** i = inventory;
while( length != 0)
{
free(*i);
length--;
++i;//notice the difference (++i) instead of (++(*i))
}
free(inventory);
}
答案 2 :(得分:2)
我们只能推测inventory
及其内容是如何生效的,但由于您单独释放它们,因此您可能也单独malloc()
个。但是你通过ptr
和ptr++
来看看它们,它们假定了连续的分配结构成员,就像你在数组中一样。
然而,malloc()
将以任何方式返回连续分配的连续存储,但没有任何保证(并且平均实现也不会这样做)。
这就是为什么你看到它们超过预期的148个字节。由于库存可能是分配指针的数组,因此您要做的是:
while( length != 0)
{
free(*inventory);
length--;
++inventory;
}
答案 3 :(得分:1)
指针算术不是问题...问题是你对如何布局数组的假设是错误的。
我猜你做了类似的事情:
length = 3;
inventory = (struct book**) malloc(sizeof(struct book *) * length);
...
inventory[0] = (struct book*) malloc(sizeoof(struct book));
inventory[1] = ... etc ;
然后将ptr分配给inventory [0];
ptr = *inventory;
但是你假设
++ptr == inventory[1];
但事实并非如此。