realloc在失败时是否会释放原来的缓冲区?

34

如果 realloc 失败并返回 NULL,先前的缓冲区是否被释放还是保持不变?我在 man 手册中没有找到这个特定信息,我很不确定该怎么做。如果内存已被释放,则双重释放可能会带来风险。如果没有释放,则会发生泄漏。

4个回答

34
不,它不会做到。这一点经常让我感到恼火,因为你不能仅仅使用:
if ((buff = realloc (buff, newsize)) == NULL)
    return;

如果你希望在失败时释放原始资源,那么在你的代码中,你需要这样做:

而不能只是简单地调用free函数。

if ((newbuff = realloc (buff, newsize)) == NULL) {
    free (buff);
    return;
}
buff = newbuff;

当然,我理解在失败时保持原始缓冲区不变的理由,但我的使用情况已经足够弹出,以至于我通常编写自己的函数来处理该情况,例如:

// Attempt re-allocation. If fail, free old buffer, return NULL.

static void *reallocFreeOnFail (void *oldbuff, size_t sz) {
    void *newbuff = realloc (oldbuff, sz);
    if (newbuff == NULL) free (oldbuff);
    return newbuff;
}

// Attempt re-allocation. If fail, return original buffer.
// Variable ok is set true/false based on success of re-allocation.

static void *reallocLeaveOnFail (void *oldbuff, size_t sz, int *ok) {
    void *newbuff = realloc (oldbuff, sz);
    if (newbuff == NULL) {
        *ok = 0;
        return oldbuff;
    }

    *ok = 1;
    return newbuff;
}

C11标准中相关的部分如下所示(我用斜体标出):

7.20.3.4 realloc函数

如果ptr是一个空指针,realloc函数将为指定大小的内存块行为类似于malloc函数。否则,如果ptr不匹配之前由callocmallocrealloc函数返回的指针,或者如果该空间已经被调用freerealloc函数释放,则行为未定义。如果无法为新对象分配内存,则老对象不会被释放,并且其值不会改变。


重复的条件跳转(在调用“free”之前一次检查“NULL”,然后再次在“free”内部检查)在常见情况下(指针不是“NULL”时)成本更高,而在罕见情况下(指针为“NULL”时)只有微小的帮助。我认为这是一个净损失。 - R.. GitHub STOP HELPING ICE
其实,@R说得很对。主要情况几乎肯定会有一个非NULL的“old”,所以我的检查并没有太大作用。我会把它去掉。 - paxdiablo
1
如果 sz==0,你可能还应该跳过调用 realloc,直接调用 free(old)。这是因为关于 realloc 返回 0 的含义存在一定程度的分歧。有些人声称,如果成功将内存调整为大小为 0,并且实现具有 malloc(0)==NULL,则返回 0(并且不设置 errno)是合法的,在这种情况下,随后的 free(old) 将是一个危险的双重释放。我会写出以下函数:void *new=0; if (!sz || !(new=realloc(old,sz))) free(old); return new; - R.. GitHub STOP HELPING ICE
实际上,为了在realloc调整大小为零时安全地返回“成功”,您可能需要在这种情况下return malloc(1);... 唉... - R.. GitHub STOP HELPING ICE
@R..:令人困扰的是,POSIX表示realloc(ptr, 0)可能无法释放ptr并且不应该使用,但realloc(3)表示它等同于free(ptr),因为free()void类型且无法指示失败,所以不会失败。 - Kevin
如果你使用的是BSD系统,或者有可用的libbsd(它在大多数Unix系统中都可用,包括GNU/Linux发行版),那么你可以使用reallocf(3)函数。 https://manpages.debian.org/testing/libbsd-dev/reallocf.3.en.html - alx - recommends codidact

5

realloc()函数返回一个指向新分配内存的指针,该指针适合用于任何类型的变量,并且可能与ptr不同,如果请求失败,则返回NULL。 如果size等于0,则返回NULL或适合传递给free()的指针。 如果realloc()失败,则原始块将保持不变; 它不会被释放或移动。

malloc(3) - Linux man page


2

如果realloc()失败,则不会更改先前缓冲区的内容。

realloc(3)手册:

realloc()返回指向新分配的内存的指针,该内存适合于任何类型的变量,并且可能与ptr不同,如果请求失败,则返回NULL。如果大小等于0,则返回NULL或适合传递给free()的指针。如果realloc()失败,则原始块保持不变;它不被释放或移动。


1
不会的。realloc通过malloc或calloc分配的动态内存来增加/减少内存。如果realloc在增加内存时失败,它将返回NULL,但不会更改先前分配的内存。由于realloc从先前分配的内存的基地址计算新的内存分配,因此它不对内存执行任何操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接