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

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

  1. First
  2. Second

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

【问题讨论】:

  • 你知道Linux不保留内存吗? malloc 和 realloc 永不失败。相反,如果您的内存不足,您的程序将会崩溃。

标签: c memory-leaks memory-management realloc


【解决方案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 的一些实现只需执行 malloc、memcpy、free。这使得 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 中的”。 :-)
      猜你喜欢
      • 1970-01-01
      • 2011-08-30
      • 2018-12-17
      • 2014-02-08
      • 1970-01-01
      • 2016-05-12
      • 2017-07-29
      • 2020-12-11
      • 2010-11-23
      相关资源
      最近更新 更多