对于这个简单的测试,以及带有4Gb或RAM的linux机箱,0byte的交换和x86_64模式的CPU,我不能分配超过1 Gb的数组。
来源:
#include <cstdio>
int main()
{
for(int i=0;i<33;i++) {
char*a=new char[1<<i];
*a=1;
delete[]a;
printf("%d\n",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
内存没有ulimit:
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&lt;&lt; 24 * 4 = 1&lt;&lt;&lt;&lt;&lt;所需的总内存为2 * 25 *(1 <26)3355443200字节+ 50 * sizeof(指针),用于some_array + 50 *(new []开销的大小)。
答案 0 :(得分:14)
C中的裸常量是int。签名的int。
所以1 << 31
是-2147483648。
因为
1<<31
= 0x10000000
= -2147483648
尝试(size_t)1 << i
答案 1 :(得分:5)
编辑:我在其他答案中看到该问题很可能与传递给new[]
的数字变为负数有关。我同意这种情况很可能就是这种情况,我只是因为我认为它包含的信息可能与某些类似情况相关,而问题不在于使用负数调用new[]
。< / p>
首先想到的问题是你是否有足够的可用内存。使用4Gb RAM且无需交换,可分配给所有进程和内核的内存总量为4Gb。
请注意,即使您有超过1Gb的内存可用于此过程,malloc
和free
(new[]
和delete[]
下面调用的内存可能不会提供内存回到系统,实际上它们可能保留了每个获取/释放的块,因此程序的内存占用量可能高达2Gb(必须使用内核中的malloc实现来检查)尽可能多的实现确实给出了大块。)
最后,当你请求一个1Gb的数组时,你正在请求1Gb的连续的内存,而且可能只是你有更多的内存,但没有一个块足够大特别要求。
答案 2 :(得分:0)
您系统上/proc/sys/vm/overcommit_memory
和/proc/sys/vm/overcommit_ratio
的值是多少?如果关闭了内存过量使用,则可能无法分配系统上的所有内存。启用overcommit(将/proc/sys/vm/overcommit_memory
设置为0)然后您应该能够在64位系统上分配基本上无限大小的数组(当然是10 GB)。
答案 3 :(得分:0)
虽然通常情况下,在64位计算机上,您有足够的地址空间来分配几GB的连续虚拟内存,但您尝试使用new / malloc进行分配。新的/ malloc传统上不是对任何内存的请求,而是对于使用 {s,} brk 系统调用分配的内存的特定部分,它基本上移动了结尾过程数据段。我认为你应该使用 mmap 分配如此大量的内存,让操作系统可以自由选择任何地址块。