On the pleasures of memory management

Error:  Allocation from MMO_GroundClutter.cpp line 42 was allocated using new [] but was freed using delete;  should have been delete []!

I can’t say how proud I was to have had my memory management system be smart enough to print out such a cogent and useful error message.  I’m less certain about how bright an idea it was for it to do the correct thing after displaying the error, instead of crashing immediately.  This error message, for example, has been generated by the game for three days now, and I only noticed it today.  If it had crashed immediately, I would have fixed it at once.

For those who aren’t familiar with the pleasures of C++, a large part of working with the language has to do with requesting and returning blocks of memory (by which we traditionally mean RAM).  We use those blocks of memory to store data temporarily.  Textures, models, various bits of gameplay, etc.  In C, there was only one way to get a block of memory:  you called “malloc()”, passing in the size of the data block you wanted to receive.  And when you were done with that data block, you called “free()”, the same way.

In C++, for various reasons, two more methods were added:  “new” (for creating an instance of a C++ class), and “new []” (for creating a lot of instances of a C++ class in a big array).  Because these different blocks of memory contain different data and are allocated in different ways, they need to be freed in different ways.  For “new”, you must call “delete” to release the object.  For “new[]”, you must call “delete[]”.  In many memory management implementations, calling the wrong one will cause your program to crash, so it’s important to get this right.

VectorStorm’s memory management system isn’t a fast one.  I should say that up front.  When a game asks for memory, the memory management system does a pretty dumb linear search through its preallocated heap space looking for a spare area that it can hand out.  It also isn’t very memory-efficient;  it allocates extra space before and after each memory block that it hands out, storing information about how the block was allocated, by which file and which line of code, as well as boundary guards for detecting whether something has accidentally written past the end of the block.

These things all make it possible to easily detect issues like mismatched allocation/deallocations, leaks, and other places where programs have accessed memory incorrectly.  So every time I make a mistake about these things (which thankfully isn’t very often), it’s there to poke me with a stick.

It’s worth also noting that VectorStorm’s memory management also isn’t friendly to devices which want to use virtual memory (i.e. almost every modern computer or phone), since it handles all its own allocations inside of its own huge data block.  From the OS’s point of view, a VectorStorm game uses only a single memory block, which is several megabytes in size.  (In the case of MMORPG Tycoon 2, it’s currently about 600 megabytes in size, and will eventually be even larger.  Most of my other games are in the 6-30 megabyte range).

Between it’s lack of speed and lack of friendliness toward virtual memory support (or fragmented memory in general on the target device, as is often the case on, for example, the iPhone), I expect that for any major release I’d swap over to using the regular OS-provided allocation/deallocation functions instead of VectorStorm’s built-in ones.  But for the purpose of development, it’s great having a system like this there to catch errors early.  I know from long experience that it can be a real bear to track these things down otherwise.