Question

I am currently having a problem with declaring or filling a large array with data because I get a dialog box saying "Out of memory", originating from CMemoryException.

I am trying to create an array or vector (tried both) with around 50000 elements of an object, where sizeof(MyObjectClass) returns around 37000 bytes.

If I try to just fill up a vector or a CArray element by element, then I get around to filling with somewhere near 16000 elements before getting the Out Of Memory exception. That should be close to 600MBs?

I have 8GB RAM on the machine and only 4GB are being used according to Windows Task Manager. So the amount of physical RAM should not impose a problem. I am running C++ MFC in Visual Studio 2010, 32-bit.

Also if I try to write

MyObjectClass* heaparray = new MyObjectClass[50000];

then I immediately get that very same Out of memory error, on that very row.

Any ideas? Thank You in advance!

UPDATE: I have also tried to simply create a TestStruct with the fields:

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];

Still the same...I get a "Out of Memory" exception when executing the last line of code. Isn't one of the great things with the heap supposed to be possibility to be limited only by RAM (more or less) when handling big data. And yet...since it crashes already at 600MB of allocated space I cannot agree that that is very big data either...or should I? :/

Was it helpful?

Solution

This is a fun one. Both Vectors and arrays are stored contiguously in memory as stated here.

You are not only looking for 1850000000 bytes (1.72295 gigabytes) in memory, but one unbroken chunk of memory that big. That will be hard to find. If you switch to a different data structure that does not do contiguous storage (say a linked list) then you may be able to store that much.

Note: that will also make each object just a bit bigger.

What would be best would be to see if there is any way to just buffer the objects; load only the ones you will update and load the others on the fly when you need them. I have my doubts that you are doing cpu operations on more than one at a time. If you do it right (with threading most likely) you won't even suffer any slows from reading/writing them.

More information about what you are working on would be helpful. There may even be a way to just have an array filled with a type identifier, if your object has less than 2,147,483,647 (size of int) variations. You could store an array of integers that the class could be generated from (a toHash and fromHash that would be 50000 * 4 bytes = 195.312 kilobytes), that may work for you too. Again, it depends on what you are working on.

OTHER TIPS

I will try to expand on @user1884803's answer:

  1. Don't use a pointer to an array. Even Visual Studio 2010 has <vector>. But see next point.

  2. Don't use a vector either... Specially if you really want to read all your MyObjectClass objects in RAM. As the other answer said, even if you have 4Gbytes free, you probably don't have 1.7Gbytes of contiguous free memory.

  3. So, if you really, really, want to read all your objects in RAM (because the processing you want to do on them is non-linear, or needs many records at the same time in memory), use a std::list<MyObjectClass> or, if you need a "key" to access each record, use a std::map<KeyType, MyObjectClass>. BUT...

  4. You really should try not reading 1.8Gbytes of objects to RAM. Even if you have that much RAM lying around unused, it's just not a good practice. If you can, read each object from the database, process it, and write it back to the database discarding the used object, not accumulating the whole thing in RAM. If you need and if it improves your speed, you can save part of it in a std::list, std::map, or even in a std::vector, and on demand refresh other parts of the objects from the database.

That way, your program would go from:

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

to something like

if( cmd.Open() ) {
  do {
    MyObjectClass obj = cmd.Read();
    // JUST PROCESS obj here and go to next

    cmd.Save(obj); // or whatever
  } while( cmd.MoveNext() );
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top