结构的指针算法给出了奇怪的结果

时间:2013-12-10 19:27:03

标签: c pointers

我有以下功能:

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 而且我的堆已经损坏了。

任何建议:为什么?

4 个答案:

答案 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()个。但是你通过ptrptr++来看看它们,它们假定了连续的分配结构成员,就像你在数组中一样。

然而,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];

但事实并非如此。