内存分配函数返回的点

Points returned by memory allocation functions

提问人:Zeta-Squared 提问时间:6/4/2022 最后编辑:Zeta-Squared 更新时间:6/4/2022 访问量:51

问:

我正在从 K.N.King 的书中学习 C,并且正在完成第 17 章的编程项目。我在完成第一个项目时遇到了一个自作自受的错误。这是程序的未定义行为,因为我正在向 realloc() 传递从早期 malloc() 调用返回的指针的副本,因为 realloc() 调用发生在 main() 以外的函数中。在重新阅读了本章的部分内容后,我意识到 realloc() 在这种情况下具有未定义的行为。

我试图寻找为什么会这样,但无济于事。那么,这里有人知道为什么传递给 realloc() 的指针必须是从 malloc()、calloc() 或 realloc() 的早期调用返回的指针,而不是这些指针的副本?另外,每当我们想要调整内存块的大小时,我们不是天生就总是复制 realloc() 返回的指针吗?

int num_parts = 0, max_parts = 10;

int main(void)
{
    struct part *inventory = malloc(max_parts * sizeof(*inventory));
    \\...
    switch(ch) {
        \\...
        case 'i':
            insert(inventory, &num_parts, &max_parts);
            break;
        \\...
    }
}

void insert(struct part *inventory, int *num_parts, *max_parts)
{
    if (*num_parts == *max_parts) {
        *max_parts += 10;
        struct part *temp = realloc(inventory, max_parts * sizeof(*temp));
        if (temp != NULL)
            inventory = temp;
        else
            printf("Error:...\n");
    }
    \\...
}
C 指针 引用 RealLoc 按值传递

评论


答:

4赞 Vlad from Moscow 6/4/2022 #1

该函数按值接受指针insertinventory

void insert(struct *inventory, int *num_parts, *max_parts)

insert(inventory, &num_parts, &max_parts);

这意味着该函数处理原始指针值的副本。在函数中更改副本,例如

    if (temp != NULL)
        *inventory = temp;

不影响 main 中声明的原始指针的值。

您需要通过指向指针的指针通过引用传递指针。

那是

insert( &inventory, &num_parts, &max_parts);

该功能将看起来像

void insert(struct **inventory, int *num_parts, *max_parts)
{
    if (*num_parts == *max_parts) {
        *max_parts += 10;
        struct part *temp = realloc( *inventory, max_parts * sizeof(*temp));
        if (temp != NULL)
            *inventory = temp;
        else
            printf("Error:...\n");
    }
    \\...
}

在这种情况下,取消引用函数中的函数参数,我们可以直接访问原始指针(对象),从而可以更改它。struct **inventory

评论

0赞 Zeta-Squared 6/4/2022
啊,好吧。我认为这应该与数组相同,通过向函数传递数组的名称,我们只是将指针传递到数组的第一个元素,但我们仍然可以以这种方式操作数组的元素?
0赞 Vlad from Moscow 6/4/2022
@Zeta平方 事实上,我们通过指向数组第一个元素的指针通过引用传递数组的元素。使用指针算术和取消引用运算符,我们可以更改数组的任何元素。同样,如果我们要在函数中更改指针的值,我们需要通过引用(通过指向它的指针)传递指针。
0赞 Zeta-Squared 6/4/2022
是的,谢谢你,我现在明白了。对于数组,将数组名称传递给函数不会更改指针指向的内容,而是更改所指向的对象。在这种情况下,我已经提出,由于内存块我位于完全不同的位置,我需要能够更改指针指向的内容,因此我需要将原始指针的地址传递给函数,即 .谢谢你的帮助,我已经接受了你的回答。struct part **inventory
0赞 ShadowRanger 6/4/2022
@Zeta平方:需要明确的是,问题不在于您传递了指针的副本。没关系,无法分辨区别(如果您开始 Vlad 的函数并传递给 ,它会正常工作)。问题在于您需要替换调用方的原始指针,如果没有指向调用方存储的指针,则无法做到这一点。reallocreallocstruct part *localinventory = *inventory;localinventoryrealloc
0赞 Zeta-Squared 6/4/2022
@ShadowRanger 是的,我现在明白了。谢谢。