如果失败,realloc 会释放前一个缓冲区吗?

Posted

技术标签:

【中文标题】如果失败,realloc 会释放前一个缓冲区吗?【英文标题】:Does realloc free the former buffer if it fails? 【发布时间】:2010-12-09 02:02:08 【问题描述】:

如果 realloc 失败并返回 NULL 是前一个缓冲区被释放还是保持原样?我没有在手册页中找到那条特定的信息,我很不确定该怎么做。如果内存被释放,那么双重释放可能会有风险。如果没有,就会发生泄漏。

【问题讨论】:

【参考方案1】:

不,它没有。这方面经常让我烦恼,因为你不能只使用:

if ((buff = realloc (buff, newsize)) == NULL)
    return;
如果您想要在您的代码中

在失败时释放原件。相反,您必须执行以下操作:

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。主要的情况几乎肯定会有一个非空的old,所以我的支票并没有真正买那么多。我会摆脱它。 您可能也应该跳过调用realloc,如果sz==0 则直接调用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; 实际上要在realloc-to-size-zero 上获得安全的“成功”回报,在这种情况下,您可能需要return malloc(1);...呃...... @R..: 麻烦的是,POSIX 说realloc(ptr, 0) 不能释放ptr 并且不应该使用,但是realloc(3) 说它“相当于free(ptr), " 不能失败,因为 free()void 并且无法指示失败。【参考方案2】:

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

malloc(3) - Linux man page

【讨论】:

【参考方案3】:

没有。如果realloc() 失败,则不会更改之前的缓冲区。

男人realloc(3):

realloc() 返回一个指向新分配内存的指针,这适合 为任何类型的变量对齐,并且可能与 ptrNULL 不同,如果 请求失败。如果 size 等于 0,则 NULL 或适合的指针 传递给free() 被返回。如果realloc() 失败,则保留原始块 原封不动;它没有被释放或移动。

【讨论】:

【参考方案4】:

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

【讨论】:

以上是关于如果失败,realloc 会释放前一个缓冲区吗?的主要内容,如果未能解决你的问题,请参考以下文章

堆栈缓冲区溢出会导致堆损坏吗?

linux机制

清空缓存区,避免对缓存区中残留数据对下次读入造成影响

IOS操作完成后如何释放vImage缓冲区

Android OpenGL动态大小FloatBuffer?

Android:如果我使用 SmsManager 发送短信,它会自动重新发送失败的短信吗?