4

假设我有 10 kB 堆并像这样混合 C 和 C++ 代码。

char* block1 = malloc(5*1024); //allocate 5
char* block2 = new[](4*1024); // allocate 4

是否有 C 堆和 C++ 堆,或者两者都只有一个堆?所以“新”知道堆的前 5 kb 已经分配了吗?

4

3 回答 3

7

可能有也可能没有单独的 C 和 C++ 堆。你不能编写一个符合标准的 C++ 程序来区分它们,所以这完全取决于实现。

该标准描述了默认行为的第一步,operator new如下所示:

执行循环:在循环内,函数首先尝试分配请求的存储空间。尝试是否涉及对 C 标准库函数 malloc 或 aligned_alloc 的调用未指定。[new.delete.single]/4.1。

malloc其本身而言,标准说:“[ aligned_alloc, calloc, malloc, 和realloc] 不要尝试通过调用::operator new()“ [c.malloc]/3 来分配存储空间。

malloc所以目的是可以从调用operator new,但这不是必需的。

在实践中,operator new调用malloc.

于 2019-09-03T18:23:00.077 回答
0

内存分配的工作方式是,用户空间程序首先通过系统调用(*nix 上的sbrkmmap )从操作系统请求一个或多个内存页。这通常由包含在“C 库”中的 malloc 实现(有几个)来完成。这个 malloc 实现然后管理它(成功)请求的所有页面。这是在用户空间中完成的

回到您的问题:::operator new的大多数实现只会中继到 malloc。但是你总是可以使用不同的分配器实现,甚至在你的程序中混合几个(参见:内存池)。*

这就是标准要求您不要混合 malloc/free 和 new/delete 的原因。

*) 许多 malloc 实现存在很多小对象的问题(这在 C++ 中很常见),这是更改分配器的一个很好的理由。

于 2019-09-03T18:55:45.580 回答
0

一个有效的实现应该是直接使用系统调用brk()/mmap()而不是通过malloc(). 尽管查看 gnu 实现,但事实并非如此。它在malloc()内部使用。

于 2019-09-03T20:45:55.327 回答