::operator new(size_t) 是不是使用 malloc()?

Posted

技术标签:

【中文标题】::operator new(size_t) 是不是使用 malloc()?【英文标题】:Does ::operator new(size_t) use malloc()?::operator new(size_t) 是否使用 malloc()? 【发布时间】:2016-04-21 04:29:53 【问题描述】:

::operator new(size_t) 是在内部调用malloc(),还是直接使用系统调用/特定于操作系统的库调用? C++ 标准是怎么说的?

在this answer 中说:

malloc() 保证返回与任何标准类型对齐的地址。 ::operator new(n) 仅保证返回与不大于 n 的任何标准类型对齐的地址,如果 T 不是字符类型,则只需 new T[n] 返回与 T 对齐的地址.

这表明不能要求new() 调用malloc()

注意:question 关于 operator new 所做的所有事情其他,而不是分配。

【问题讨论】:

类似的问题是:是否可以使用free() 而不是delete 来释放使用new 关键字分配的指针。 【参考方案1】:

operator new 如何实现的细节是标准库的特定实现的属性——甚至不是编译器或操作系统。我熟悉一个(gnu)并知道其他 3 个 - CLang、Apache 和 MSFT。他们都在operator new 中使用malloc(),因为它让库开发人员的生活变得更加轻松。

如果不使用malloc(),开发人员将不得不在内存分配方面重新实现很多,并在代码中大量使用依赖于操作系统的逻辑来实际请求内存。当malloc() 已经存在时,没有人愿意这样做。但绝不是他们有义务使用它。

【讨论】:

【参考方案2】:

可以,而且通常可以。 在 Windows 上(更具体地说,在 VC++ 上),调用链看起来像

operator new 打电话给malloc 打电话给HeapAlloc

HeapAlloc 是一个 Windows API 函数,用于从特定堆分配内存。 当进程启动时,它会分配一个堆(CRT 堆),所有标准分配都在其中占用内存。

不,没有义务调用 malloc。由库开发人员/最终用户开发人员决定他们想要从哪里获得内存。

例如,我可以创建一个单线程程序。通常堆分配器在分配/释放发生时锁定堆锁,以防止堆上的致命竞争条件。 但如果我的程序是单线程的,我就没有问题。 我可以选择使用 WinApi HeapCreate 创建自己的堆并传递 HEAP_NO_SERIALIZE,这会使堆跳过锁。然后我可以将operator new 与普通的HeapAlloc 一起使用。在这种情况下,我可以让 new 使用与 malloc 不同的功能。

另一种有时*的低级方法是使用VirtualAlloc 分配巨大的内存块,然后在有人调用new 时传递重新计算的内存地址。

(所有这些方法都很少完成,根据我的经验,它们对执行时间的改善很小)

【讨论】:

【参考方案3】:

是的,它可能会调用 malloc - 在带有 VS 和标准运行时库的 Windows 下,它确实会调用 malloc

您可以重载 new 运算符并调用您自己的分配函数。在我工作的应用程序中,我们有来自 Doug Lea 的自定义 malloc,其中包含许多针对嵌入式系统的自定义。 windows调用malloc是因为它调用了heapAlloc,这是windows下的标准堆分配函数。它还允许使用 CrtDbg api 调试分配错误。

为了让答案更正式,我查阅了标准,在 §18.6.1.1 中,我发现 new

执行一个循环:在循环内,函数首先尝试 分配请求的存储空间。 尝试是否涉及调用 标准 C 库函数 malloc 未指定

因此未指定是否使用 malloc - 它可能会使用它。

【讨论】:

而且必须它调用malloc? @einpoklum,当然不是。这是实现细节。此外,答案在技术上并不正确——重要的是您使用什么标准库,而不是什么编译器或操作系统。但是,对于任何库实现者来说,重用 malloc() 的现有功能而不是自己编写特定于操作系统的编码是有意义的。 @SergeyA:从技术上讲,该标准谈论的是“实现”。如果您通过从一个地方获取编译器、从另一个地方获取标准库和从第三方获取链接器来构建自己的实现,那么您就是实现者并负责正确执行。大多数人从单一来源获得他们的实现(并称其为“编译器”)。 @MartinBonner,这在技术上肯定不是一个正确的术语。例如,作为编译器的 CLang 没有 std 库(同时提供一个独立的库),而 Apache 提供了一个没有编译器的库。 什么是“技术上不正确的术语”? “实施”?该标准的第一句话是“本国际标准规定了 C++ 编程语言的实现要求”。该库是该实现的一部分。

以上是关于::operator new(size_t) 是不是使用 malloc()?的主要内容,如果未能解决你的问题,请参考以下文章

operator new 如何知道内存已分配[重复]

C# 中的“var”是不是类似于 C 中的“size_t”?

C++内存管理(new operator/operator new/operator delete/placement new)

c++ new operator和operator new,delete operator和operator delete

C++内存管理机制学习笔记:重载operate new/::operator new..../new()

C++内存管理机制学习笔记:重载operate new/::operator new..../new()