realloc后的空闲内存如何

问题描述 投票:6回答:6

在此代码中释放内存的正确方法是什么?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( void ){

    char *string1, *string2;
    string1 = (char*) malloc(16);

    strcpy(string1, "0123456789AB");

    string2 = realloc(string1, 8);

    printf("string1 Valor: %p [%s]\n", string1, string1);
    printf("string2 Valor: %p [%s]\n", string2, string2);

    free(string1);
    free(string2);
    return 0;
}

由于两个指针指向同一个方向

c
6个回答
16
投票

我认为你的困惑来自(无灵感)表达式“自由指针”(你在帖子中使用过,但自从编辑后)。你没有自由指针。你释放记忆。指针只是告诉哪个内存。


在你的例子中,你有:从malloc获得的记忆。 string1指向这个记忆。然后,当你调用realloc时,会获得一个新的内存块(可能从相同的地址开始,可能不是),但realloc会在需要时小心释放旧的内存块(因此是未定义的行为,可以自行访问或释放它)。 string2指向这个新的内存块。

所以你必须free只是从realloc获得的内存块。 string2指向那个记忆。


7
投票

简而言之,没有。

对于the C Standard

7.22.3.5 realloc功能

...

realloc函数释放ptr指向的旧对象,并返回指向由size指定大小的新对象的指针。新对象的内容应与解除分配之前的旧对象的内容相同,直到新旧大小中的较小者为止。新对象中超出旧对象大小的任何字节都具有不确定的值。

一旦你调用realloc(),你没有free()传递给realloc()的指针寻址的内存 - 你必须free()指针realloc()返回的内存。 (除非realloc()返回NULL,在这种情况下,原始的内存块 - 传递给realloc() - 必须是free()'d。)


3
投票

当您调用realloc时,返回的指针与原始指针相同,或者返回一个新指针并且原始指针变为无效。在第一种情况下,在freestring1上调用string2会导致双重释放,因为指针是相等的。在第二种情况下,在free上调用string1是双重免费的,因为它已经被释放了。

所以无论哪种方式,你都有一个双倍自由,导致undefined behavior

realloc的手册页:

void *realloc(void *ptr, size_t size);

realloc()函数将ptr指向的内存块的大小更改为size字节。内容将在从区域开始到新旧尺寸的最小范围内保持不变。如果新大小大于旧大小,则不会初始化添加的内存。如果ptr为NULL,则对于所有size值,调用等效于malloc(size);如果size等于零,并且ptr不为NULL,则该调用等效于free(ptr)。除非ptr为NULL,否则必须由之前调用malloc(),calloc()或realloc()返回。如果指向的区域被移动,则完成自由(ptr)。

realloc()函数返回一个指向新分配的内存的指针,该内存适用于任何类型的变量,可能与ptr不同,如果请求失败,则返回NULL。

同样来自free的手册页:

free()函数释放ptr指向的内存空间,该内存空间必须由之前调用malloc(),calloc()或realloc()返回。否则,或者如果之前已经调用了free(ptr),则会发生未定义的行为。如果ptr为NULL,则不执行任何操作。

你只需要free(string2)


1
投票

简短的回答:在你的代码中,调用free(string2)是正确的,并且足够了。调用free(string1)不正确。

当您调用realloc(并假设调用成功)时,其返回值(存储在string2中)成为引用您拥有的一块内存的唯一方法。

可能是realloc“就地”调整了你的记忆块,这意味着string2string1的值是相等的。在这种情况下,调用free(string1)是错误的,因为你将两次相同的指针释放。

可能是realloc在调整大小的过程中将您的数据移动到新的位置。在这种情况下,string2string1的值是不相等的。但在这种情况下,在找到数据的新位置并将其复制到那里后,realloc会自动为您释放旧块。因此,再次调用free(string1)是错误的,因为你释放了一个已经释放的指针。


1
投票

realloc视为等同于:

void *
realloc(void *old, size_t new_size)
{
    size_t old_size = magic_internal_function_that_knows_the_size_of(old);
    void *new = malloc(new_size);
    if (new == NULL)
        return NULL;
    memcpy(new, old, new_size > old_size ? old_size : new_size);
    free(old);
    return new;
}

如果你有魔术函数可以计算指针的分配大小,你可以像这样自己实现reallocmalloc几乎必须在内部为free工作。

realloc也可以做一些聪明的事情,比如弄清楚你要重新分配到一个较小的尺寸,只是释放你的部分分配,或者发现你正在增加你的分配,并且在适应它之后有足够的空间。但是你不需要考虑这些情况。认为realloc是malloc + memcpy + free不会误导你,除非你需要记住realloc失败并返回NULL意味着它没有做free


0
投票

realloc implicity释放输入,它可能根本不做任何事情,但你不能在重新分配内存后释放它。所以

char *string1, *string2;
string1 = (char*) malloc(16);
....
string2 = realloc(string1, 8);  // this line implicitly frees string1

free(string1); // this is wrong !!!
free(string2);
© www.soinside.com 2019 - 2024. All rights reserved.