Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;在堆上分配大数组会得到;“内存不足异常”;_C++_Arrays_Memory - Fatal编程技术网

C++ C++;在堆上分配大数组会得到;“内存不足异常”;

C++ C++;在堆上分配大数组会得到;“内存不足异常”;,c++,arrays,memory,C++,Arrays,Memory,我目前在用数据声明或填充一个大数组时遇到问题,因为我得到一个对话框,上面写着“内存不足”,这是由CMemoryException产生的 我正在尝试创建一个包含50000个元素的数组或向量(尝试两者),其中sizeof(MyObjectClass)返回大约37000字节 如果我试着一个元素一个元素地填充一个向量或一个CArray元素,那么在得到内存不足异常之前,我会先填充大约16000个元素。这应该接近600MBs 我的机器上有8GB内存,根据Windows任务管理器,目前只使用4GB内存。因此,

我目前在用数据声明或填充一个大数组时遇到问题,因为我得到一个对话框,上面写着“内存不足”,这是由CMemoryException产生的

我正在尝试创建一个包含50000个元素的数组或向量(尝试两者),其中sizeof(MyObjectClass)返回大约37000字节

如果我试着一个元素一个元素地填充一个向量或一个CArray元素,那么在得到内存不足异常之前,我会先填充大约16000个元素。这应该接近600MBs

我的机器上有8GB内存,根据Windows任务管理器,目前只使用4GB内存。因此,物理RAM的数量不应该造成问题。我在Visual Studio 2010,32位,c/+mfc中运行C++。 如果我想写的话

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];
还是一样…我在执行最后一行代码时遇到“内存不足”异常。
在处理大数据时,堆的最大优点不应该是仅受RAM(或多或少)的限制。然而……由于它已经在600MB的分配空间崩溃,我也不能同意这是非常大的数据……或者我应该这样做吗?:/

这是一个有趣的游戏。如前所述,向量和数组都连续存储在内存中

您不仅要在内存中查找
1850000000字节
1.72295千兆字节
),还要查找一个如此大的未中断内存块。这将很难找到。如果您切换到不进行连续存储的不同数据结构(比如链表),那么您可能能够存储这么多

注意:这也会使每个对象稍微大一点

最好的办法是看看是否有任何方法可以缓冲这些对象;仅加载您将更新的内容,并在需要时动态加载其他内容。我怀疑您一次对多个cpu执行操作。如果你做得对(最有可能是线程),你甚至不会因为读/写它们而受到任何影响


更多关于你正在从事的工作的信息会有所帮助。如果对象的变量小于2147483647(int的大小),甚至可能有一种方法可以让数组填充类型标识符。您可以存储一个整数数组,该类可以从中生成(toHash和fromHash为50000*4字节=195.312 KB),这可能也适用于您。同样,这取决于你在做什么。

我将尝试扩展@user1884803的答案:

  • 不要使用指向数组的指针。甚至VisualStudio2010也有
    。但请看下一点

  • 也不要使用
    向量
    。。。特别是如果您真的想读取RAM中的所有
    MyObjectClass
    对象。正如另一个答案所说,即使您有4G字节的可用空间,您也可能没有1.7GB的连续可用内存

  • 因此,如果您真的想读取RAM中的所有对象(因为您想对它们进行的处理是非线性的,或者需要在内存中同时有许多记录),请使用
    std::list
    ,或者,如果您需要一个“键”来访问每个记录,请使用
    std::map
    但是…

  • 您确实应该尝试而不是将1.8GB的对象读取到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...
    }
    

    MyObjectClass是什么样子的?在32位编译器上分配的内存不太可能超过4GB如果每个对象的实际容量为37000字节,那么您至少需要1764.16毫巴,因为您需要大量的连续内存,即使您有大量的物理内存,也无法使用。即使您使用的是64位操作系统和8GB的RAM,32位用户模式进程默认情况下只能访问2GB的内存。请参阅:。你不能把你的程序编译成x64版本吗?谢谢你的回复!我需要从DB(网络)中获取很多行,然后对每个行执行一些操作,然后将其全部刷新到本地DB表中。因此,我可以在网络数据库的多次往返中分配大量内存。所以我有一个命令cmd。我使用ans SQL查询调用cmd.Open(),该查询获取大量数据(大约50000行),然后循环直到cmd.MoveNext()失败。每次循环我都会将当前元素添加到向量或数组中。16000行之后,我的内存出现异常。链表…也许我应该尝试一下,我只是>>不相信我不能用数组/向量更容易地在堆上分配那么多RAM…因为它在仅分配600MB之后崩溃:/(另请参阅我第一篇文章中的“我的UUpdate”部分)连续存储只是虚拟内存。它只需要虚拟内存地址的连续范围,而不需要物理存储。好的,现在我有时间用std:list进行测试,是的,它确实有效!连续内存似乎是原因。谢谢你的回答!谢谢你的回复!是的,但我明白你的意思,但问题是最终所有这些数据都需要以某种形式从一个网络数据库传输到一个本地数据库表。通过一行一行地获取数据,然后一行一行地保存数据,到一个很远的网络数据库进行50000次往返
    if( cmd.Open() ) {
      do {
        MyObjectClass obj = cmd.Read();
        // JUST PROCESS obj here and go to next
    
        cmd.Save(obj); // or whatever
      } while( cmd.MoveNext() );
    }