【问题标题】:Shrink int array C收缩 int 数组 C
【发布时间】:2012-08-24 11:17:57
【问题描述】:

刚开始学习C,遇到如下问题:

我需要在 C 中缩小一个整数数组,最后删除元素。通过删除我的意思是释放。常见的答案是为较小的数组分配新内存,然后将原始数组的所有项( -items to remove )复制到新分配的内存中,然后 free() 原始数组。

因为我必须处理非常个大数组,所以我宁愿跳过复制部分。

是否可以创建一个指针变量,指向“接近原始数组的末尾”,大小为“数组末尾 - 接近末尾”,然后释放该指针?

提前致谢

【问题讨论】:

  • 您可以使用realloc 进行缩小。不能保证,但某些实现实际上会返回您传递的原始指针,而无需复制任何内容。
  • 你考虑过使用realloc吗?
  • realloc 是否也会释放最后丢弃的任何元素?我不知道如何测试...顺便感谢您的快速响应!
  • 它会将分配空间的大小调整为您告诉它的任何大小(更大或更小),我将在下面提供一个示例。
  • 要回答您的部分问题,free() 不可能通过传递“接近末尾”的指针来释放部分内存块。这几乎肯定会导致崩溃或堆损坏。

标签: c arrays trim shrink


【解决方案1】:

我会使用realloc。 Realloc 可能会复制内存,但这仍然比滚动您自己的内存管理来解决复制问题更有效。

有些人会告诉您,当结果大小较小时,不会复制任何表现良好的 C 库。他们可能是对的。但是,我不使用或编写商业 C 库,所以就我而言,这种说法是未经证实的。

【讨论】:

  • 除非在调试选项阻止释放任何内存的特殊情况下,如果大小缩小(或保持不变),所有商业库重新分配都会避免复制......为什么不呢?
  • 同意;尽管据我所知,这并不能保证/在规范中。
  • 人们一直在谈论规范中的保证,以回应我的 cmets 对此只字未提。该规范不保证 malloc 将返回除 NULL 之外的任何内容。了解规范很重要,但如果一个人都明白这一点,那就是学究气,而不是工程。
  • 我不反对任何特定的观点,我保证如果你给予我同样的礼貌,我不会把话放在你嘴里。
  • 我只是指出,当我谈论“所有商业库重新分配”时,关于规范的评论是不合理的。当然,规范中不能保证 realloc 不会复制……也不能保证它会成功……但这对于练习程序员来说根本不感兴趣。
【解决方案2】:

C 标准库中的 realloc 函数可能是您想要的。

在您的情况下,它可能不会执行任何复制操作,因为内存管理器没有理由分配新的内存区域。只有新旧大小之间的差异可能被系统回收为可用内存。

如果您使数组更大,则会发生复制,因为 malloc 和朋友不保证“当前”区域之后的内存实际上是空闲的。如果是,那么没关系,当前内存分配会被扩大。 如果没有,则需要找到更大的可用内存区域,并且可以将其分配到内存中的几乎任何位置。

【讨论】:

  • @JimBalter:未定义 realloc 例程以使释放的内存可用于新分配。是否这样做取决于实施。 malloc 系列例程很难很好地实现,因为它必须服务于各种各样的应用程序以及时间和内存之间的权衡。花费额外的空间和时间来跟踪从大量分配中释放的少量内存可能效率不高。
  • @EricPostpischil 我没有说它是如何定义的。我已经编写了几个商业 malloc/reallocs 并且研究了其他人的代码并且非常了解它们是如何实现的。 “可能不会”释放内存是完全错误的......绝大多数可用的重新分配都是这样做的。并且未能跟踪从大分配中释放的内存会泄漏内存。当然,它可以选择将大小稍小的 realloc 视为 noop,但要释放足够的缓冲区,并且该空间将可供重用。
  • @KeithMiller 如果您 malloc 一个大缓冲区,然后将其重新分配到稍小的大小,则该 realloc 可能只是一个 noop,而分配的大小保持不变。但这只是针对小的差异,而不是大的差异。 (在实践中,当然不是“根据定义”。)
  • @JimBalter:实现不会忘记从大量分配中释放的少量内存。它只会保留大量分配。直到整个分配被释放或另一个重新分配充分缩短了请求的空间以使实现认为值得拆分内存,内存才可用于重用。您报告的经验不足以证明 realloc 使释放内存可用的无条件声明。这取决于实现。
  • @JimBalter:从规范中推断行为是工程,而不是迂腐。假设没有文档的有利实现会导致错误。用少量内存(尤其是当记账成本超过释放空间大小时的净负数)来换取速度的质量并不低;它正在优化性能。
【解决方案3】:

你有没有想过使用realloc

int main(void)
{
    int *array = NULL, *tmp;

    if(!(array = malloc(5 * sizeof(int)))) return 1;
    if(!(tmp = realloc(array, 2*sizeof(int)))) 
    {
        free(array);
        return 1;
    }
    array = tmp;
}

您可以在没有tmp 指针的情况下执行此操作,而只需使用array = realloc(array, 2*sizeof(int)))),但这可能会导致以后出现问题。

【讨论】:

    【解决方案4】:

    可以设计一个内存管理器来实现这一点,但没有一个常用的内存管理器具有此属性。您可以编写自己的 mm 并将其用于这些数组。

    【讨论】:

      猜你喜欢
      • 2011-04-16
      • 2016-04-13
      • 2022-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-04
      相关资源
      最近更新 更多