【问题标题】:What if NULL and size 0 are passed to realloc()?如果将 NULL 和大小 0 传递给 realloc() 会怎样?
【发布时间】:2017-07-07 06:15:57
【问题描述】:

是否定义了行为实现?如果 NULL 和 size == 0 传递给realloc()

int main(void)
{
    int *ptr = NULL;

    ptr = realloc(ptr, 0);

    if(ptr == NULL)
    {
        printf("realloc fails.\n");
        goto Exit;
    }

    printf("Happy Scenario.\n");

Exit:
    printf("Inside goto.\n");

return 0;
}

上面的代码应该打印“realloc failed”,对吧?但不是吗?我在某处读到这个对realloc 的调用也可能返回NULL。什么时候发生?

【问题讨论】:

  • 可能的重复没有解决void *vp = realloc(NULL, 0);行为的具体点。
  • 我在这里同意@Jonathan。看起来引用的 dup 缺少关于重新分配 0 个元素的行为的讨论,以及有关您将返回的指针的信息。旧的 Microsoft 平台在分配 0 个元素时会遇到很多麻烦。

标签: c memory-management realloc


【解决方案1】:

此行为由实现定义。

来自C standard

第 7.22.3.5 节 (realloc):

3 如果ptr 是空指针,则realloc 函数的行为类似于指定大小的malloc 函数。 否则,如果ptr 与内存管理先前返回的指针不匹配 函数,或者如果空间已通过调用释放 freerealloc 函数,行为未定义。如果 无法为新对象分配内存,旧对象是 未解除分配,其值不变。

所以realloc(NULL, 0)malloc(0) 相同

如果我们再看第 7.22.3.4 节 (malloc):

2malloc 函数为大小由size 指定且值不确定的对象分配空间。

3malloc 函数返回空指针或指向分配空间的指针。

标准没有说明传入0时会发生什么。

但是如果你看看 Linux man page:

malloc() 函数分配 size 个字节并返回一个指向 分配的内存。内存未初始化。 如果大小为 0, 然后malloc() 返回 NULL 或唯一的指针值,它可以 稍后成功传递给free()

它明确声明返回的值可以被释放但不一定是NULL。

相比之下,MSDN 说:

如果 size 为 0,malloc 在堆中分配一个长度为零的项,然后 返回指向该项目的有效指针。始终检查从 malloc,即使请求的内存量很小。

所以对于 MSVC,你不会得到一个 NULL 指针。

【讨论】:

  • 谢谢!这很有帮助,特别是与 MSDN 的对比。
  • “标准没有说明传入 0 时会发生什么。”确实如此,只是在部分介绍而不是在 realloc 段落中。对于 C1x,它在“7.22.3 内存管理函数”下:“如果请求的空间大小为零,则行为是实现定义的:要么返回空指针,要么行为就像大小为非零一样值,但返回的指针不得用于访问对象”。
【解决方案2】:

电话

realloc(NULL, size);

等价于

malloc(size);

malloc() 在被要求分配 0 字节时做了什么有点不清楚,标准没有说明。我认为它是实现定义的。基本上“没关系”;它要么返回NULL,要么返回一个指针,您可以在其中合法地访问零字节,这些非常相似。两者都可以传递给free()

【讨论】:

  • 不,不要将NULL 传递给free() - 这是不好的做法,可能会导致崩溃,具体取决于实现。
  • "如果 ptr 是空指针,则函数什么也不做"。来源:cplusplus.com/reference/cstdlib/free
【解决方案3】:

realloc(3) 文档:

如果 ptr 为 NULL,则调用等效于 malloc(size),对于所有 size 值

malloc(3) 文档:

如果 size 为 0,则 malloc() 返回 NULL,或稍后可以成功传递给 free() 的唯一指针值。

所以是的,它是实现定义的,您将获得 null 或可以释放的指针。

【讨论】:

  • 如果你得到一个非空指针,你得到的指针应该被释放以避免泄漏,但不能被取消引用(因为它提供了0字节的合法访问内存)。
  • @JonathanLeffler "...应该释放您获得的指针以避免泄漏" 适用于所有分配为 0 或非零大小且不返回 NULL 的指针。最终他们应该被释放以避免泄漏。 OTOH,如果malloc(0) 返回非NULL,立即释放它可能会减少内存使用,这可能是个好主意,但这不是泄漏问题。
  • 我想知道有什么好处,如果有的话,保证一个非空指针是唯一的,而不是简单地指定每个值从一个零大小的malloc()calloc()返回, 或realloc() 将被视为不同用于传递给free()realloc(),但可能恰好与从其他零大小操作接收到的指针进行比较。不为零大小的分配请求执行分配是有利的,但大小为零的请求会返回一个指向静态虚拟对象的指针,freerealloc 都会忽略...
  • ...将使零大小的请求可以避免分配任何东西而不必返回空指针。
猜你喜欢
  • 1970-01-01
  • 2012-01-12
  • 2020-10-15
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 2012-06-21
  • 2010-11-21
  • 1970-01-01
相关资源
最近更新 更多