简体   繁体   English

无法使用新的[] / C ++ / Linux / x86_64分配2-4 Gb的RAM

[英]Can't allocate 2-4 Gb of RAM with new[]/ C++/Linux/ x86_64

For this easy test, and the linux box with 4Gb or RAM, 0byte of swap and CPU in x86_64 mode, I can't allocate more than 1 Gb of array. 对于这个简单的测试,以及带有4Gb或RAM的linux机箱,0byte的交换和x86_64模式的CPU,我不能分配超过1 Gb的数组。

Source: 资源:

#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);
 }
}

Run: 跑:

$ 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

There is no ulimit for memory: 内存没有ulimit:

virtual memory          (kbytes, -v) unlimited
data seg size           (kbytes, -d) unlimited

Why the error? 为什么错误?

Glibc is 2.3.4, kernel is 2.6.9 Glibc是2.3.4,内核是2.6.9

UPDATE: Compiler is gcc4.1 更新:编译器是gcc4.1

Thanks! 谢谢! The test definitely has a error, 1ull<<i gives me up to 31 (2gb). 测试肯定有一个错误, 1ull<<i给我高达31(2gb)。 This error was unintended. 此错误是无意的。 But the real failed code is 但真正失败的代码是

 for(j=0;j<2;j++)
  for(i=0;i<25;i++)
   some_array[j][i] = new int[1<<24];

so there is no sign overflow in the real code. 所以实际代码中没有符号溢出。

Size of int is 4 byte: int的大小是4个字节:

$ echo 'main(){return sizeof(int);}'| gcc -x c - && ./a.out; echo $?
4

the every request will be for 1<<24 * 4 = 1<<26; 每个请求将为1 << 24 * 4 = 1 << 26; total memory required is 2*25*(1<<26) 3355443200 bytes + 50*sizeof(pointer) for some_array + 50*(size of new[] overhead). 所需的总内存为2 * 25 *(1 << 26)3355443200字节+ 50 * sizeof(指针),用于some_array + 50 *(new []开销的大小)。

A naked constant in C is an int. C中的裸常数是int。 A signed int. 签名的int。 So 1 << 31 is -2147483648. 所以1 << 31是-2147483648。 because 1<<31 = 0x10000000 = -2147483648 因为1<<31 = 0x10000000 = -2147483648

Try (size_t)1 << i 尝试(size_t)1 << i

EDIT: I see in other answers that the issue is most probably related with the number passed to new[] becoming negative. 编辑:我在其他答案中看到,这个问题很可能与传递给new[]变成负面相关。 I agree that that is most probably the case, I am leaving this answer only because I think that it contains information that might be relevant in some similar cases, where the issue is not with calling new[] with a negative number. 我同意这种情况很可能就是这种情况,我只是因为我认为它包含的信息可能与某些类似情况相关,而问题不在于使用负数调用new[]


The first question that comes to mind is whether you have enough available memory. 想到的第一个问题是你是否有足够的可用内存。 With 4Gb RAM and no swap the total amount of memory that can be allocated to all processes and the kernel is 4Gb. 使用4Gb RAM且无交换,可分配给所有进程内核的内存总量为4Gb。

Note that even if you had more than 1Gb of memory available for the process, malloc and free (that are called underneath by new[] and delete[] might not give the memory back to the system, and they might in fact keep each one of the acquired/released blocks, so that the memory footprint of your program might go as high as 2Gb (would have to check this with the malloc implementation in your kernel, as many implementations do give back big blocks). 请注意,即使你有超过1Gb的内存可用于进程, mallocfree (在new[]delete[]下面调用可能不会将内存返回给系统,并且实际上它们可能保留每个内存获取/释放的块的大小,以便程序的内存占用量可能高达2Gb(必须使用内核中的malloc实现来检查这一点,因为许多实现确实会返回大块)。

Finally, when you request an array of 1Gb you are requesting 1Gb of contiguous memory, and it might just be the case that you have much more memory but none of the blocks is large enough for that particular request. 最后,当您请求1Gb的数组时,您正在请求1Gb的连续内存,并且可能只是您拥有更多内存,但没有一个块足够大以满足该特定请求。

Although is generally true that on 64bit machine you have plenty of address space to allocate several GB of continuous virtual memory, you are trying to allocate it using new/malloc. 虽然通常情况下,在64位计算机上,您有足够的地址空间来分配几GB的连续虚拟内存,但您尝试使用new / malloc进行分配。 New/malloc are traditionally not requests for any memory , but for a specific part of the memory which is allocated using the {s,}brk system call which basically moves the end of the process data segment. 传统上,new / malloc不是对任何内存的请求,而是对使用{s,} brk系统调用分配的内存的特定部分,该调用基本上移动了进程数据段的末尾。 I think that you should allocate such large amount of memory using mmap which leaves the OS free to choose any address block. 我认为你应该使用mmap分配如此大量的内存,让操作系统可以自由选择任何地址块。

What are the values of /proc/sys/vm/overcommit_memory and /proc/sys/vm/overcommit_ratio on your system? /proc/sys/vm/overcommit_memory/proc/sys/vm/overcommit_memory/proc/sys/vm/overcommit_ratio是什么? If you have memory overcommitting turned off, you may not be able to allocate all the memory on your system. 如果关闭了内存过量使用,则可能无法分配系统上的所有内存。 With overcommit turned on (set /proc/sys/vm/overcommit_memory to 0) then you should be able to allocate essentially unlimited size arrays (certainly 10s of GB) on a 64-bit system. 启用overcommit(将/proc/sys/vm/overcommit_memory为0)然后您应该能够在64位系统上分配基本上无限大小的数组(当然是10 GB)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM