为什么我不能在我的向量中预留1,000,000,000的空间?

5
当我输入以下代码时,输出结果为1073741823。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
  vector <int> v;
  cout<<v.max_size();
  return 0;
}

但是,当我尝试将向量的大小调整为1,000,000,000时,通过v.resize(1000000000);程序停止执行。如何使程序能够分配所需的内存,当它似乎应该能够做到呢?

我在Windows 7中使用MinGW。我有2 GB RAM。难道不可能吗? 如果不可能,我不能将其声明为整数数组并摆脱它吗?但即使那也行不通。

另一件事是,假设我要使用一个可以轻松处理这么多数据的文件。 如何让它同时读写。 使用fstream file("file.txt', ios::out | ios::in );并没有创建文件。但是假设文件存在,我无法同时进行读写。 我的意思是这样的:

假设文件内容为111111 然后如果我运行:-

#include <fstream>
#include <iostream>
using namespace std;
int main()
{
  fstream file("file.txt",ios:in|ios::out);
  char x;
  while( file>>x)
  {
    file<<'0';
  }
 return 0;
}

文件的内容现在不应该是 101010 吗?读取一个字符,然后用 0 覆盖下一个字符?或者如果整个内容一次性读入某个缓冲区,文件中不应该至少有一个 0 吗?1111110? 但是文件的内容仍然没有改变。请解释一下。 谢谢。

4
欢迎来到Stack Overflow!这是两个独立的问题。通常情况下,您应该分别提出它们。 - Mehrdad Afshari
3
这是两个非常不同的问题。请您拆分成两篇问题发布吗? - wilhelmtell
谢谢您。很抱歉,由于内存分配不起作用,我尝试在文件中进行相同的操作,但出现了一组不同的错误。因此,我把问题放在了一起。下次我会确保单独提出每个问题。 - shreedhar
我建议如果你想要回答两个问题,就把你的“另一件事”移到一个新的线程中。 - Clifford
5个回答

14
  1. 32位进程只能在单个时刻寻址4GB的地址空间。通常,这4GB的地址空间中的许多空间用于映射其他东西。您的向量将占用太多连续的地址空间(40亿字节),这很可能不可用。

  2. 您应该内存映射文件。请参见mmap


这个讨论:http://stackoverflow.com/questions/2791330/which-is-better-in-general-map-or-vector-in-c/2791491#2791491 可能是相关的。 - Clifford
2
Win32的地址空间限制为2GiB。我认为Linux应该是3GiB。 - Vincent Robert
1
@Vincent:在Windows上也有3GB开关,尽管2GB是默认值:http://technet.microsoft.com/en-us/library/bb124810%28EXCHG.65%29.aspx - sbk
由于内存映射文件依赖虚拟内存,因此地址范围限制仍然存在。 - Clifford
1
@Clifford:你会注意到这个例子是一次处理一个字节。也就是说,vipersnake005 理解“内存不足”的解决方案是“一次处理一个块”。他在应用这个原则到修改操作时遇到了问题。内存映射文件恰好解决了这个问题:它们将文件的一部分映射到地址空间中,对该地址空间的修改会被写回到文件中。 - MSalters
显示剩余4条评论

1

STL实现能够处理的最大值是一回事;操作系统可用内存的最大值是另一回事;你正在碰到后者。

例如,你可能能够创建一个由那么多个char元素组成的向量。无论哪种方式,除非你实际拥有那么多的内存(加上操作系统和其他运行中的程序所需的内存),否则不要期望出色的性能;访问这样的向量无疑会导致大量的磁盘抖动,因为系统会将内存从磁盘中分页进出。

此外,具有32位地址空间的处理器(或在运行32位操作系统时,无论物理地址空间如何)只能寻址4GB(物理或虚拟),因此存在架构限制。此外,某些操作系统限制用户空间;例如,Win32中的用户空间固定为2GB。各种版本的Win64人为地限制了用户空间,以便允许微软收取不同的价格,因此使用Win64并不能保证具有足够的地址空间。


0
然而,当我尝试将向量调整大小为1,000,000,000(v.resize(1000000000);)时,程序停止执行。当似乎应该能够分配所需的内存时,如何使程序能够分配所需的内存取决于C++ STL实现,但通常调整大小的行为会导致应用程序保留比您要求的更多的内存。

0
一个整数占用四个字节,因此1,000,000,000个整数将占用约3.72GB的空间。

2
不,它将需要(至少)4 GB 或大约3.72 GiB 的空间。有关详细信息,请参阅二进制前缀 - fredoverflow
9
有点学究气!我见过这个术语在常见的使用场景只有维基百科。在那种情况下(读者可能不是计算机专家),它有助于消除歧义,但是在这里我认为我们都非常清楚他的意思,没有任何歧义。 - Clifford

0

你要求在连续的序列中分配十亿个整数。除了找到如此巨大的连续空间的困难之外,你根本就没有那么多的空间。请记住,在普通的32位系统上,一个整数占用32位或4字节。将其乘以十亿,你已经超过了2GB的空间限制。此外,std::vector允许预留比你请求更多的空间。

关于你的第二个问题,如果你使用同一个 fstream 对象同时进行读写,请确保在读写之前调用 seekg()seekp()


有道理,它不应该能够分配那么多。但是为什么 v.maxsize() 允许我分配更多的空间呢? - shreedhar
关于seekg和seekp,我曾经认为,读和写只有一个文件指针?如果有两个,我能写入文件然后不使用seekg(0)读取全部内容吗? - shreedhar
vector::max_size()并不会“允许”你分配那么多空间。它只是告诉你标准库实现所施加的限制。你的硬件是否能够达到这个限制是另一回事。 - wilhelmtell
如果您写入文件,然后希望使用同一对象进行读取,则需要将其定位到所需读取的位置。同样,如果您希望使用相同的对象将内容写入从中读取的文件,则必须将其定位到要写入的位置。写入和读取都会自动更改获取和放置指针,因此您必须自己调整它们。个人而言,我发现只要可以,就更容易使用“ifstream”对象来读取文件,并使用“ofstream”来写入文件。 - wilhelmtell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接