【问题标题】:How operator new knows that memory is allocated [duplicate]operator new 如何知道内存已分配[重复]
【发布时间】:2015-05-01 10:30:57
【问题描述】:

在C++中,可以operator new如何保存一块内存被分配的信息? AFAIK,它不能在恒定时间内工作,并且必须在堆中搜索空闲内存。或者,也许不是关于 C++,而是关于 OS?

附:不知道是不是标准规定的,是OS管理的还是C++管理的,具体怎么实现呢?

【问题讨论】:

  • new 如何分配内存是编译器供应商的实现细节。一些new 实现在内部使用malloc(),有些则没有。但很少有人直接进入操作系统,通常在两者之间有一个运行时库,管理内存分配(除其他外)。代码不应该关心方式或其他方式。它要求编译器new 一些内存,并得到一个指针作为回报。如何管理内存由编译器决定。
  • 我认为 C++ 语言标准没有定义它,但最简单的方法是多分配几个字节,并在其中存储下一个可用内存块的地址(所以堆通常实现为链表)。
  • 由操作系统完成的内存管理。
  • 简短的回答是它很可能不会这样做。内存管理器主要跟踪可用于分配的内存块。当前分配的块只是从其可用块列表中删除。当您调用delete 时,该块被添加回空闲列表。
  • @Juergen 操作系统没有理由不能管理小内存块;我实际上使用了一种 C 实现,其中 malloc 和 free 只是对操作系统的请求。然而,大多数人不能非常有效地做到这一点,因此出于效率原因,malloc 和free 通常从大的进程内存块中分配。除非你要求很大的东西; malloc 直接进入操作系统获取几兆的情况并不少见。

标签: c++ memory new-operator


【解决方案1】:

new 维护一个数据结构来跟踪单独分配的块。有很多方法可以做到这一点。通常,使用某种链表。

这里有一个small article 来说明这一点。

【讨论】:

    【解决方案2】:

    new 通常是在 malloc/free 的基础上实现的。

    malloc/free 是如何实现的?答案是:这取决于实施。令人惊讶的是:Malloc 通常根本不跟踪分配的块!唯一的事情,malloc 大部分时间都在做,就是在分配的块“之前”添加一些包含块大小的信息。这意味着,当您分配 40 个字节时,它将分配 44 个字节(在 32 位机器上)并在前 4 个字节中写入大小。它将这个chunk+4的地址返回给你。

    Malloc/free 跟踪一个空闲列表。 freelist 是尚未(尚未)返回给操作系统的已释放内存块的列表。 Malloc 搜索空闲列表,当需要一个新块并且有合适的块可用时使用它。

    但我在这里给出了关于 malloc/free 的更令人筋疲力尽的答案: How do malloc() and free() work?

    一个附加信息:

    许多分配器不跟踪分配的块这一事实的一个含义:当您通过 free 或 delete 返回内存并传入一个以前未分配的指针时,您将破坏您的堆,因为系统不是能够检查指针是否有效。关于它的真正丑陋的事情是,在这种情况下,您的程序不会立即转储,而是在错误原因发生后的任何时间......因此这个错误真的很难找到。这就是 C/C++ 中的内存处理如此困难的原因之一!

    【讨论】:

    • "Malloc 通常根本不跟踪分配的块!"但是free()不取block的大小,怎么知道呢?
    • 好的,没错。我忘记了这一点 - 并将添加我的答案。
    • 至少有一个广泛的实现将分配块和空闲块放在同一个列表中。该列表是有序的,这使得合并空闲块(直到在malloc 中的搜索到达空闲块时才发生)非常简单。 (我怀疑现代实现要复杂得多,对小块进行了优化等)
    • @JamesKanze:我不熟悉所有的实现,当然还有最新的实现,我不知道。这就是原因,我试着认真回答。还具有特殊的安全功能,包括今天,当然总是有新的发展。但作为开发人员,最好不要依赖于这样一个事实,malloc/new 会保存损坏的指针。
    • 但即使实现将分配的块保留在列表中也是如此。唯一的问题是您正在描述一种特定的可能实现(即使我从未见过它也可能实际使用过)。还有很多很多,我怀疑你描述的那个不是特别常见。
    【解决方案3】:

    没有简单、标准的答案。 operator new/operator delete 的大多数实现最终转发到malloc/free,但是有一个 许多不同的算法可以用于这些。唯一的就是 或多或少普遍的是分配通常会分配一点 超过请求,并使用额外的内存(通常在地址前面 实际返回)来维护一些额外的信息:要么是实际 分配的大小或指向块末尾的指针(或下一个块的开头 堵塞)。除了一些算法将保持相同大小的分配 在一起,并且能够从地址确定大小。没有 您的问题的单一答案。

    【讨论】:

      猜你喜欢
      • 2017-01-31
      • 1970-01-01
      • 2015-11-21
      • 1970-01-01
      • 2012-12-22
      • 2020-10-05
      • 1970-01-01
      • 2014-01-23
      • 2015-12-07
      相关资源
      最近更新 更多