【问题标题】:Can realloc() expand into (and overwrite) subsequent data?realloc() 可以扩展到(并覆盖)后续数据吗?
【发布时间】:2016-07-14 22:40:32
【问题描述】:

我现在正在学习 C/C++,对内存分配函数的行为感到困惑,尤其是 realloc()

假设我分配了十个ints:

int * i = malloc(sizeof(int) * 10);

我使用该数组一段时间,但后来意识到我需要更多空间,所以我将 i 重新分配给 20 ints:

int * j = realloc(i, sizeof(int) * 20);
i = j;

但是,似乎重新分配之前的堆可能包含一些其他数据紧接在最初分配给 i 的内存空间之后,因为在分配和重新分配 i 之间我可以执行另一个 malloc , 这可能会在i 之后分配空间。

然后,当我重新分配时,添加到 i 的新空间似乎会立即扩展到(并覆盖)数据。

会发生这样的事情吗?如果是这样,我应该怎么做才能避免意外覆盖数据?

【问题讨论】:

  • 如果没有足够的可用空间来直接修复增加,realloc 会将现有数据移动到有足够空间的地方。这就是它返回指针的原因。
  • ..或者,当然,失败。
  • 总是检查malloc和朋友的结果! (以及通常会遇到程序相关错误的函数)
  • Can realloc() expand into (and overwrite) subsequent data? - 没有。

标签: c memory malloc dynamic-memory-allocation realloc


【解决方案1】:

您无需担心realloc 会覆盖任何内容。您也不需要使用中间值来保存新指针,除非您想尝试从realloc 故障中恢复。如果没有,那么正常的做法是:

ptr = realloc(ptr, new_size);

它会做以下三件事之一:

  1. 如果有足够的未分配空间来扩展旧指针,那么它可能会这样做,在这种情况下它将返回原始指针。

  2. 否则会尝试分配新空间,复制旧数据,释放旧存储。

  3. 如果无法分配新空间,它可能会返回NULL,就像malloc一样。因此,在尝试使用它之前,您应该始终检查返回值。在NULL 返回的情况下,最简单的操作是打印错误消息并退出。如果要恢复并继续运行,则需要保存旧指针值,以便释放它并避免内存泄漏,

请注意,realloc 也可用于缩小和增加存储空间。换句话说,你可以给它一个比以前分配的更小的大小。

【讨论】:

  • 还有第三种可能:realloc可能尝试分配新空间,失败,返回NULL。在这种情况下,如果您没有保存指针的旧值,则会发生内存泄漏。这就是为什么总是建议使用临时指针的原因(检查返回值也是如此)。当然,如果您满足于让您的应用程序在分配失败时崩溃并烧毁,您可以忽略这种做法。但至少应该提到一个事实。
  • @rici 处理这些 NULL 分配的推荐做法是什么?
  • @rici 我添加了一条关于NULL 返回值可能性的评论。我想我认为人们会检查它是理所当然的。如果realloc 失败,我通常只会打印一条错误消息并退出,在这种情况下,我并不真正关心旧的指针值。但可以肯定的是,如果你想做精细的错误恢复,你可以保存它。
  • @ostrichofevil 如果您只需打印一条错误消息并在NULL 返回时退出,那么这是迄今为止最简单的事情。
  • @ostrichofevil:这取决于您的应用程序。对于非关键、非服务器、非数据库应用程序,退出失败可能没问题。但是如果你有一个需要清理的应用程序,你需要优雅地退出。例如,如果您有一个多线程服务器,您将希望释放与该线程关联的内存,因此您将需要旧的指针值。
猜你喜欢
  • 1970-01-01
  • 2020-09-09
  • 2018-03-04
  • 2011-09-11
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 2011-04-20
相关资源
最近更新 更多