malloc()与new []的内存开销

时间:2015-07-21 21:39:24

标签: c++ memory malloc

我想保留一块内存(1GB)来将数据加载到其中进行分析。每条记录大约10K字节,并且至少有100k条记录。最初我打算在c ++代码中使用malloc,但我被建议反对它。

现在,将使用char * block = new char [1000000000]需要额外的内存来存储指向数组中每个1,000,000,000个元素的指针吗?使用char * block = malloc(1000000000 * sizeof(char))是否需要比new []创建更少的额外内存?

我的目标是尽可能少地使用内存,并且不希望在内存中淹没记录。

谢谢:)

5 个答案:

答案 0 :(得分:2)

在我的Linux机器上:

的malloc

//malloc.cc
#include <cstdlib>
int main() { char* block = (char*) malloc(1000000000); }

运行:

$ make malloc
$ valgrind ./malloc 2>&1|grep total
==23855==   total heap usage: 1 allocs, 0 frees, 1,000,000,000 bytes allocated

//new.cc
int main() { char* block = new char[1000000000]; }

运行:

$ make new
$ valgrind ./new 2>&1|grep total
  ==24460==   total heap usage: 2 allocs, 0 frees, 1,000,072,704 bytes allocated

对于不同的值,72,704B开销保持不变。

答案 1 :(得分:2)

为了让operator delete[]与非POD一起正常工作,数组的大小(单个size_t)通常放在整个块的开头,而第一个对象放在第一个适当对齐的地址。

对于POD,operator new[](没有初始值设定项)通常与malloc相同。

使用初始化程序(同样,使用POD类型),结果取决于编译器:它可以转换为元素上的循环,或缩减为memset

鉴于您打算分配大量内存,malloc的结果取决于运行时 - 某些实现对块大小有严格的上限。

如果您定位到Windows,则可以将VirtualAlloc用于此大小的内容。同样,在* nix上使用mmap

答案 2 :(得分:1)

你问:

  

现在,使用char * block = new char[1000000000]是否需要额外的内存来存储指向数组中每个1,000,000,000个元素的指针?

绝对没有。

从C ++ 11标准(第5.3.4节新增)

  

5当分配的对象是数组时(即使用 noptr-new-declarator 语法或 new-type-id 类型-id 表示数组类型),new-expression产生指向数组初始元素(如果有)的指针。

关键是你回到一个指向数组初始元素(如果有的话)的指针

您还问:

  

使用char * block = malloc(1000000000 * sizeof(char))创建的额外内存要少于new[]吗?

该标准未指定与使用任一分配方法相关的开销。在大多数实现中,与两种方法相关联的存储器开销应该大致相同,如果不完全相同的话。如果不是这样,我会感到惊讶。

答案 3 :(得分:0)

new[N]比预期要多得多。它在开头存储计数器[N](知道需要用delete []调用多少析构函数)并在它之后返回一个内存块。

答案 4 :(得分:0)

如果您使用new分配一个字符数组,您将获得一个字符数组。每个元素都没有其他指针。您只需获得一个与malloc()相似的大型连续内存区域。

new将要做的是分配内存,然后调用构造函数,在你的情况下,它将不会产生任何后果,因为这只是一个Plain Old Data数组。

我使用Visual Studio 2013进行快速检查并使用调试编译并查看Windows任务管理器中的内存分配,因为我首先调整了new然后malloc()并查看了数字每一步的内存分配都是一样的。

如果存储区域太大,您可能会遇到页面错误,因为操作系统会在访问内存区域的各个部分时将您的大内存区域打入和转出。不确定你真的可以做任何事情,我也不确定这是一个很大的担忧。部分任何交换行为将取决于您拥有的物理内存量以及其他服务和应用程序及其内存使用情况的混合。