operator new 如何知道内存已分配[重复]
Posted
技术标签:
【中文标题】operator new 如何知道内存已分配[重复]【英文标题】:How operator new knows that memory is allocated [duplicate] 【发布时间】: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
直接进入操作系统获取几兆的情况并不少见。
【参考方案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
,但是有一个
许多不同的算法可以用于这些。唯一的就是
或多或少普遍的是分配通常会分配一点
超过请求,并使用额外的内存(通常在地址前面
实际返回)来维护一些额外的信息:要么是实际
分配的大小或指向块末尾的指针(或下一个块的开头
堵塞)。除了一些算法将保持相同大小的分配
在一起,并且能够从地址确定大小。没有
您的问题的单一答案。
【讨论】:
以上是关于operator new 如何知道内存已分配[重复]的主要内容,如果未能解决你的问题,请参考以下文章