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

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

【问题讨论】:

    标签: realloc


    【解决方案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..: 麻烦的是,POSIXrealloc(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 从先前分配的内存的基地址计算新的内存分配,它不会对内存执行任何操作

        【讨论】:

          猜你喜欢
          • 2020-09-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-09
          • 2017-09-25
          • 1970-01-01
          • 2021-12-14
          • 1970-01-01
          相关资源
          最近更新 更多