使用 realloc 是不是安全?

Posted

技术标签:

【中文标题】使用 realloc 是不是安全?【英文标题】:Is it safe to use realloc?使用 realloc 是否安全? 【发布时间】:2012-02-22 16:49:54 【问题描述】:

前段时间,我的一个朋友告诉我不要使用realloc,因为它不安全,但他无法告诉我原因,所以我对该主题进行了一些研究,最接近我怀疑的参考是:

    First Second

我想知道我是否可以继续在我的代码中使用realloc ,或者它是否不安全,是否有任何其他方法可以重新分配内存?

【问题讨论】:

你知道Linux不保留内存吗? mallocrealloc 永不失败。相反,如果您的内存不足,您的程序将会崩溃。 【参考方案1】:

使用realloc 非常安全。这是在 C 程序中重新分配内存的方法。

但是,您应该始终检查返回值是否存在错误情况。不要落入这个常见的陷阱:

p = realloc(p, new_size); // don't do this!

如果失败,realloc 返回NULL,您将无法访问p。而是这样做:

new_p = realloc(p, new_size);
if (new_p == NULL)
    ...handle error
p = new_p;

【讨论】:

这取决于您的 C 库。 realloc 的一些实现只需执行 mallocmemcpyfree。这使得 realloc 不是很有用......【参考方案2】:

两篇链接文章中的第一篇提出了两个投诉,超出了此处已经提出的“检查调用成功”点。

完成后,旧内容将被丢弃并留在内存中的某个位置。对于擦除所有数据痕迹很重要的安全内存应用程序,这种行为是不合适的。

这是一个有效的点如果您碰巧存储了敏感数据(例如私钥、未散列的(!)密码等)并希望让漏洞更难恢复数据或其他系统上的进程窃取数据。

由于它会移动内存,任何指向该内存的旧指针都会变得无效,并可能导致程序崩溃或其他行为异常。

这点对我来说似乎是无稽之谈。他们提出的解决方案也好不到哪里去,他们malloc(),复制然后free() 具有相同净效果的原件 - 地址已更改。如果您想避免移动内存,可能可以使用一些特定于平台的调用来执行此操作,前提是您安排在它们附近有足够的可用地址空间。如果您先验知道要保留多少地址空间,那么您可能一开始就不会考虑调用realloc()

如果您在赌 realloc() 永不移动,一直在增长,那么您可能有更大的问题需要担心,而切换到 malloc() + 复制 + free() 不可能解决这个问题。


除了“正确检查你的返回值点”之外,第二篇文章中最有趣的一点是警告:

不要一次重新分配 1 个字节的缓冲区。

他们警告:

这保证会搅动你的内存堆

这是一个潜在的有效观点,但它并不是对realloc() 本身的批评;如果您使用malloc()+copy+free(),也会发生同样的情况。真正的解决方法是明智地增加缓冲区,无论您如何增加它们,或者更好地预先分配正确大小的块。

他们也有观点

使用 realloc 将内存返回给系统。

他们在这里是正确的,因为使用 0 以外的任何大小实际上可能不会返回。它可能不会让事情变得更糟,但这种用法似乎仍然是过早“优化”的一个例子。再次修复是使用合理大小的分配开始。

排序答案:它不是不安全的,但也不是解决所有问题的神奇方法。

【讨论】:

【参考方案3】:

realloc 本身是安全的,但安全地使用它有点棘手——我会说我见过的大约 85-90% 的代码使用它不 安全地这样做。问题是realloc 返回 NULL 以指示失败 - 但是当它这样做时,您作为输入提供的指针仍然有效(前提是您没有将其分配大小调整为 0)。

因此,当且仅当 realloc 返回一个非空指针时,您必须将来自 realloc 的返回分配给您作为输入提供的指针。如果它返回一个空指针,你之前的指针是有效的,但是分配没有被调整大小。

另请注意,许多人认为realloc 只能在您放大分配时失败和/或移动分配。实际上,即使您减少分配大小,它也可能会失败(尽管这不太可能)或将数据移动到不同的位置(更有可能)。

【讨论】:

【参考方案4】:

就像 C 中的所有东西一样,只要你知道你在做什么,就可以了。

(知道你在做什么包括检查错误,不要使用旧指针等)

【讨论】:

我认为问题是“我需要做什么?”,所以这并没有真正回答它 好吧,他说I want to know if I can continue to use realloc。答案是肯定的。 当我发布该评论时,您只有答案的第一句话 我反对“像 C 中的一切”。 C 中的一件事,gets,永远都不好。当然严格来说 C11 现在是“C”,所以 gets 不再是“C 中的”。 :-)

以上是关于使用 realloc 是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

使用 realloc() 使 memmove() 安全 [重复]

为啥使用 std::vector 而不是 realloc? [关闭]

找出分配的内存是不是被 C 中的 realloc() 函数释放

为啥使用 realloc() 时会出现双重释放或损坏错误?

realloc 使用详解(分析realloc invalid pointer指针无效等错误)

替换 realloc (C --> C++)