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

发布于 2024-11-07 23:37:34 字数 1245 浏览 5 评论 0 原文

对于这个简单的测试,以及具有 4Gb 或 RAM、0 字节交换空间和 x86_64 模式下的 CPU 的 Linux 机器,我无法分配超过 1Gb 的阵列。

来源:

#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< 给我最多 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(pointer) for some_array + 50*(new[] 开销的大小)。

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.

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:

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

Why the error?

Glibc is 2.3.4, kernel is 2.6.9

UPDATE: Compiler is gcc4.1

Thanks! The test definitely has a error, 1ull<<i gives me up to 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:

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

the every request will be for 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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

葬シ愛 2024-11-14 23:37:34

C 中的裸常量是 int。有符号整数。
所以 1 << 31 是-2147483648。
因为
1<<31 = 0x10000000 = -2147483648

尝试 (size_t)1 <<我

A naked constant in C is an int. A signed int.
So 1 << 31 is -2147483648.
because
1<<31 = 0x10000000 = -2147483648

Try (size_t)1 << i

身边 2024-11-14 23:37:34

编辑:我在其他答案中看到该问题很可能与传递给new[]的数字变为负值有关。我同意这很可能是这种情况,我留下这个答案只是因为我认为它包含在某些类似情况下可能相关的信息,其中问题不在于调用 new[]负数。


我想到的第一个问题是您是否有足够的可用内存。在 4Gb RAM 且无交换的情况下,可以分配给所有进程内核的内存总量为 4Gb。

请注意,即使您有超过 1Gb 的内存可用于该进程,mallocfree(由 new[]delete[] 可能不会将内存返还给系统,实际上它们可能会保留每个获取/释放的块,因此程序的内存占用可能高达 2Gb (必须使用内核中的 malloc 实现来检查这一点,因为许多实现确实会返回大块)。

最后,当您请求 1Gb 的数组时,您正在请求 1Gb 的连续内存,并且它可能会。如果您有更多内存,但没有一个块足够大来满足该特定请求。

EDIT: I see in other answers that the issue is most probably related with the number passed to new[] becoming negative. 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.


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.

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).

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.

明媚殇 2024-11-14 23:37:34

您系统上的 /proc/sys/vm/overcommit_memory/proc/sys/vm/overcommit_ratio 的值是多少?如果您关闭了内存过度使用,您可能无法分配系统上的所有内存。打开过量使用(将 /proc/sys/vm/overcommit_memory 设置为 0)后,您应该能够在 64 位系统上分配基本上无限大小的数组(当然是 10GB)。

What are the values of /proc/sys/vm/overcommit_memory and /proc/sys/vm/overcommit_ratio on your system? 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.

人生百味 2024-11-14 23:37:34

尽管通常情况下,在 64 位计算机上您有足够的地址空间来分配几 GB 的连续虚拟内存,但您正在尝试使用 new/malloc 来分配它。 New/malloc 传统上不是对任何内存的请求,而是针对使用 {s,}brk 系统调用分配的内存的特定部分,该系统调用基本上移动了末尾过程数据段。我认为您应该使用 mmap 分配如此大量的内存,这使得操作系统可以自由选择任何地址块。

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. 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. I think that you should allocate such large amount of memory using mmap which leaves the OS free to choose any address block.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文