我目前在使用数据声明或填充大型数组时遇到问题,因为我得到一个“内存不足”的对话框,源自CMemoryException。
我正在尝试使用大约50000个对象元素创建一个数组或向量(两者都尝试过),其中sizeof(MyObjectClass)返回大约37000个字节。
如果我尝试按元素填充向量或CArray元素,那么在获取Out Of Memory异常之前,我会在16000个元素附近填充。那应该接近600MB?
我在机器上有8GB RAM,根据Windows任务管理器只使用4GB。因此物理RAM的数量不应该带来问题。我在Visual Studio 2010中运行C ++ MFC,32位。
如果我试着写
MyObjectClass* heaparray = new MyObjectClass[50000];
然后我立即在那一行上得到了同样的内存不足错误。
有什么想法吗? 提前谢谢!
更新: 我还尝试使用以下字段创建一个TestStruct:
struct TestStruct
{
long long field1;
GUID field2;
GUID field3;
GUID field4;
TCHAR field5[256];
TCHAR field6[4];
TCHAR field7[258];
TCHAR field8[1026];
TCHAR field9[258];
TCHAR field10[16386];
TCHAR field11[258];
};
TestStruct* heapArr = new TestStruct[50000];
仍然相同......执行最后一行代码时出现“Out of Memory”异常。 在处理大数据时,堆不应该只是由RAM(或多或少)限制的可能性之一。然而......因为它已经在600MB的分配空间崩溃了,我不能同意这是非常大的数据......或者我应该? :/
答案 0 :(得分:5)
这是一个有趣的。 Vector和数组都按照所述here连续存储在内存中。
你不仅在内存中寻找1850000000 bytes
(1.72295 gigabytes
),而且一个完整的大块内存。这很难找到。如果您切换到不执行连续存储的不同数据结构(比如链接列表),那么您可以存储那么多。
注意:这也会使每个对象变得更大。
最好的方法是看看是否有任何方法可以缓冲对象;只加载你要更新的那些,并在需要时动态加载其他的。我怀疑你一次只能在多个CPU上进行cpu操作。如果你做得对(最有可能穿线)你甚至不会因读/写它们而受到任何影响。
有关您正在处理的内容的更多信息会有所帮助。如果对象的变量小于2,147,483,647(int的大小),甚至可能有一种方法可以让数组填充类型标识符。你可以存储一个可以从中生成类的整数数组(toHash和fromHash,这将是50000 * 4字节= 195.312千字节),这也可能对你有用。同样,这取决于你正在做什么。
答案 1 :(得分:2)
我将尝试扩展@ user1884803的答案:
不要使用指向数组的指针。甚至Visual Studio 2010也有<vector>
。但请参阅下一点。
也不要使用vector
...特别是如果确实想要读取RAM中的所有MyObjectClass
个对象。正如另一个答案所说,即使你有4Gbytes免费,你可能不拥有1.7Gbytes 连续可用内存。
所以,如果你真的,真的,想要读取RAM中的所有对象(因为你想对它们进行的处理是非线性的,或者在内存中同时需要很多记录),请使用std::list<MyObjectClass>
或者,如果您需要“密钥”来访问每条记录,请使用std::map<KeyType, MyObjectClass>
。的 BUT ... 强>
你真的应该尝试不读取1.8Gbytes的对象到RAM。即使你有大量RAM未使用,也只是不是一个好习惯。如果可以,请从数据库中读取每个对象,对其进行处理,然后将其写回数据库丢弃已使用的对象,而不是将整个内容累积到RAM中。如果您需要并且如果它可以提高您的速度,您可以将其中一部分保存在std::list
,std::map
,甚至std::vector
和按需中从数据库中刷新对象的其他部分。
这样,您的程序将来自:
if( cmd.Open() ) {
do {
MyObjectClass obj = cmd.Read(); // whatever is needed to read the object from the db
vectorOfObjects.push_back(obj); // or list, or map...
} while( cmd.MoveNext() );
}
for( std::vector<MyObjectClass>::iterator p = vectorOfObjects.begin(), e = vectorOfObjects.end(); p != e; ++p ) {
// process *p
}
for( std::vector<MyObjectClass>::iterator p = vectorOfObjects.begin(), e = vectorOfObjects.end(); p != e; ++p ) {
cmd.Save(*p); // see reading above, but for saving...
}
类似
if( cmd.Open() ) {
do {
MyObjectClass obj = cmd.Read();
// JUST PROCESS obj here and go to next
cmd.Save(obj); // or whatever
} while( cmd.MoveNext() );
}