无法使用新的 []/ C++/Linux/ x86_64分配 2-4 Gb 的 RAM
Can't allocate 2-4 Gb of RAM with new[]/ C++/Linux/ x86_64
对于这个简单的测试,以及具有4Gb或RAM,0字节交换和CPU的linux盒x86_64模式,我不能分配超过1 Gb的数组。
源:
#include <cstdio>
int main()
{
for(int i=0;i<33;i++) {
char*a=new char[1<<i];
*a=1;
delete[]a;
printf("%dn",i);
fflush(stdout);
}
}
跑:
$ file test
test: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV)
$ ./test
...
24
25
26
27
28
29
30
terminate called after throwing an instance of 'std::bad_alloc'
what(): St9bad_alloc
Aborted
内存没有限制:
virtual memory (kbytes, -v) unlimited
data seg size (kbytes, -d) unlimited
为什么会出现错误?
Glibc 是 2.3.4,内核是 2.6.9
更新:编译器是gcc4.1
谢谢!测试肯定有一个错误,1ull<<i
给了我最多 31 (2gb)。此错误是无意的。但真正失败的代码是
for(j=0;j<2;j++)
for(i=0;i<25;i++)
some_array[j][i] = new int[1<<24];
所以在实际代码中没有符号溢出。
int 的大小为 4 字节:
$ echo 'main(){return sizeof(int);}'| gcc -x c - && ./a.out; echo $?
4
每个请求将针对 1<<24 * 4 = 1<<26;所需的总内存为 2*25*(1<<26) 3355443200 字节 + 50*sizeof(指针) 对于 some_array + 50*(new[] 开销的大小)。
C 中的裸常量是一个整数。一个有符号的整数。所以1 << 31
是-2147483648。因为 1<<31
= 0x10000000
= -2147483648
试试(size_t)1 << i
编辑:我在其他答案中看到,该问题很可能与传递给new[]
变为负数的数字有关。我同意很可能是这种情况,我留下这个答案只是因为我认为它包含可能与某些类似情况相关的信息,其中问题不在于用负数呼叫new[]
。
想到的第一个问题是您是否有足够的可用内存。使用 4Gb RAM 且无需交换,可以分配给所有进程和内核的内存总量为 4Gb。
请注意,即使您有超过 1Gb 的内存可用于该进程,malloc
和free
(由 new[]
和 delete[]
在下面调用)可能不会将内存返回给系统,并且它们实际上可能会保留每个获取/释放的块,因此程序的内存占用量可能高达 2Gb(必须使用 malloc 实现进行检查)在你的内核中,因为许多实现确实会返回大块)。
最后,当您请求 1Gb 数组时,您正在请求 1Gb 的连续内存,可能只是您有更多的内存,但没有一个块足够大以满足该特定请求。
系统上/proc/sys/vm/overcommit_memory
和/proc/sys/vm/overcommit_ratio
的值是什么? 如果关闭了内存过度分配,则可能无法分配系统上的所有内存。 打开过度使用(/proc/sys/vm/overcommit_memory
设置为 0)后,您应该能够在 64 位系统上分配基本上无限大小的数组(当然是 10 GB 的)。
尽管在 64 位计算机上,您有足够的地址空间来分配几 GB 的连续虚拟内存,但您正在尝试使用 new/malloc 来分配它。New/malloc 传统上不是对任何内存的请求,而是针对使用 {s,}brk 系统调用分配的内存的特定部分,该调用基本上移动了过程数据段的末尾。我认为您应该使用 mmap 分配如此大量的内存,这让操作系统可以自由选择任何地址块。
- 您选择的 CPU 不支持 x86-64 指令集
- std::atomic::fetch_add是x86-64上的串行化操作
- 谷歌Play游戏服务和64位x86支持
- 在64位X86机器中读取/写双值原子
- Apple Mach-O-Linker 错误:在体系结构 x86-64 中找不到从(行)引用的变量
- x86-64 程序集:为什么偏移 25 字节
- DIS(P X)-X在GCC Linux X86-64 C 中始终导致Pointer P和Integer X的P
- 什么是 gcc Linux x86-64 C++中的有效指针
- X86-64上的C :何时通过结构/类在寄存器中返回
- x86-64 调用约定中的返回值
- C++Mac上使用Linux库(x86_64-Apple-Darwin上的elf64-x86-64)
- 如何使用64-Linux上的C 中的新操作员动态分配大型内存,例如10 g
- 如果我尝试在 c++ 中将大于 pow(2,64)-1 的值分配给无符号长整型怎么办?
- x86-64上检查指针范围是否跨越N字节对齐地址的最快方法
- 如何使用C++11为x86(-64)安全地编写测试和测试集(TATAS)自旋锁
- 在 x86-64 平台上为 C(++) 中的 64 位无符号参数计算 (a*b)%n FAST
- malloc没有分配指定的内存(64位)
- x86-64 movl and cmpl difference
- visual x86-64 MSVC++/Intel C++更改int、long等的大小
- 如何在64位x86环境下编译32位x86应用程序